Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[eclipselink-users] Eclipselink Shared Cache duplicate entities

Title: Eclipselink Shared Cache duplicate entities

Hello All,

It seems we have a problem while using shared cache in EclipseLink. We are using version 2.0.1 of EclipseLink

We have two Entities Need and NeedProduct (code snippet as below)

@SuppressWarnings("serial")
@Entity
@Table(name = "XXXX", schema = "XXX")
@org.eclipse.persistence.annotations.TypeConverter(name = "NVARCHAR2", dataType = org.eclipse.persistence.platform.database.oracle.NString.class, objectType = String.class)

public class Need implements Serializable {

        public Need() {
        }

        /**
         * primary key
         */
        @Id
        @GeneratedValue(generator = "uuid-string")
        @Column(name = "XMI_INSTANCE_TGUID")
        private String uid = null;

        public void setUid(String uid) {
                this.uid = uid;
        }

        public String getUid() {
                return uid;
        }


        @OneToMany(mappedBy = "need", fetch = FetchType.EAGER, cascade = {
                        CascadeType.REFRESH, CascadeType.ALL})
        private List<NeedProduct> needProduct = new ArrayList<NeedProduct>();

        public void setNeedProduct(
                        List<NeedProduct> needProduct) {
                this.needProduct = needProduct;
        }

        public List<NeedProduct> getNeedProduct() {
                return needProduct;
        }

        public void addNeedProduct(
                        NeedProduct listElement) {
                listElement.setNeed(this);
                needProduct.add(listElement);
        }

        public boolean equals(Object object) {

                if (object == this) {
                        return true;
                }

                if (!(object instanceof Need)) {
                        return false;
                }

                Need anotherDataObject = (Need) object;

                if ((uid == null && anotherDataObject.uid != null)
                                || (uid != null && anotherDataObject.uid == null))
                        return false;
                if (uid != null && !uid.equals(anotherDataObject.uid))
                        return false;

                return true;
        }

        /**
         * Creates a String representing the target with all attribute values shown.
         *
         * @return a String representing the state of the target
         */
        @Override
        public String toString() {

                StringBuffer result = new StringBuffer(500);
                if (uid == null) {
                        result.append("null");
                } else {
                        result.append(uid.toString());
                }
                return result.toString();
        }
}



@SuppressWarnings("serial")
@Entity
@Table(name = "XXXX", schema = "XXX")
@org.eclipse.persistence.annotations.TypeConverter(name = "NVARCHAR2", dataType = org.eclipse.persistence.platform.database.oracle.NString.class, objectType = String.class)

public class NeedProduct implements Serializable {

        public NeedProduct() {
        }

        @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = {
                        CascadeType.REFRESH, CascadeType.MERGE})
        @JoinColumn(name = "XMI_NEED_TGUID", referencedColumnName = "XMI_INSTANCE_TGUID")
        private Need need = null;

        public void setNeed(Need need) {
                this.need = need;
        }

        public Need getNeed() {
                return need;
        }

        @Id
        @GeneratedValue(generator = "uuid-string")
        @Column(name = "XMI_INSTANCE_TGUID")
        private String uid = null;

        public void setUid(String uid) {
                this.uid = uid;
        }

        public String getUid() {
                return uid;
        }

       

        public boolean equals(Object object) {

                if (object == this) {
                        return true;
                }

                if (!(object instanceof NeedProduct)) {
                        return false;
                }

                NeedProduct anotherDataObject = (NeedProduct) object;

                if ((uid == null && anotherDataObject.uid != null)
                                || (uid != null && anotherDataObject.uid == null))
                        return false;
                if (uid != null && !uid.equals(anotherDataObject.uid))
                        return false;

                return true;
        }

        @Override
        public String toString() {

                StringBuffer result = new StringBuffer(500);
                if (uid == null) {
                        result.append("null");
                } else {
                        result.append(uid.toString());
                }
                return result.toString();
        }
}


Snippet from persistence.xml

        <property name="eclipselink.weaving" value="true"/>
        <property name="eclipselink.weaving.eager" value="false"/>
            <property name="eclipselink.cache.type.default" value="SoftWeak"/>
            <property name="eclipselink.cache.size.default" value="5000"/>
            <property name="eclipselink.cache.shared.default" value="true"/>
            <property name="eclipselink.flush-clear.cache" value="DropInvalidate"/>

Here is the snippet from GenericDAOJPAImpl

        public T update(T entity) {
               
                long startTime = System.currentTimeMillis();
                try {
                        entity = entityManager.merge(entity);
                        entityManager.flush();
                        entityManager.refresh(entity);
                        return entity;
                } finally {
                        long duration = System.currentTimeMillis() - startTime;
                        if (duration > 500) {
                                LOGGER.info("Database Access duration = " + duration
                                                + "ms with update entity");
                        }                      
                }
        }


When I try to test the following scenario, it gives incorrect results

Test 1. updateNeed --> This will insert Need entity with 3 NeedProduct
Test 2. getNeed --> This will return Need entity with exact 3 NeedProduct (Correct Behavior)
Test 3. updateNeedProduct --> This Updates one of the NeedProduct received from step2 (Please note this is actual update on NeedProduct entity and not through update of its parent i.e. Need)

Test 4. getNeed --> Now this returns Need entity with 10 NeedProduct (Incorrect Behavior), DB still has 3 NeedProduct rows

        In test 3, instead of updating NeedProduct directly if I update NeedProduct through Need instance(meaning calling updateNeed() instead of updateNeedProduct()) the behavior is correct


Also when I change <property name="eclipselink.cache.shared.default" value="true"/> this to <property name="eclipselink.cache.shared.default" value="false"/> everything works fine.

Could someone please help to find the reasoning of this incorrect behavior?


Thanks, Mahipal


Back to the top