[
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