Skip to main content

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

Hello James,

Thanks for the reply. Here are some more details.

Test Methods :


1. Test Method for updateNeed

        public void test_updateNeed() throws Exception {
                System.out.println("start test_updateNeed \n");
                Need_1_0 beanRemote = lookupService();

                UpdateNeed_Parameters updateNeed_Parameters = provide_UpdateNeed_Parameters();

                Need testNewInstance = getNeedInstance();

                System.out.println("Need input " + testNewInstance + "\n");
                Need testNewResult = beanRemote
                                .updateNeed(testNewInstance, updateNeed_Parameters.businessUnit);

                assertNotNull(testNewResult);
                storeNeedInstance(testNewResult);
                System.out.println("Need " + testNewResult);
        }
       
        public Need getNeedInstance() {

                if (needInstance != null) return needInstance;

        Need need = new Need();
        need.setComment("DDD" + Integer.toString(updatesNeed));
        need.setBUID("0012");
        need.setPartner(partnerUUID);
        need.setLifeCycleStatus(LifeCycleStatus.ACTIVE);
        need.setType("AAA");
        need.setStatus("CCC");

        NeedProduct needProduct = new NeedProduct();
        needProduct.setLifeCycleStatus(LifeCycleStatus.ACTIVE);
        needProduct.setNeedProductCode("P2");

        need.addNeedProduct(needProduct);
                return need;
    }
       
    public void storeNeedInstance(Need instance) {
            needInstance = instance;       
            System.out.println("Number Of Need Products : " + needInstance.getNeedProduct().size());
    }   


2. Test method for updateNeedProduct

        public void test_updateNeedProduct() throws Exception {
                System.out.println("start test_updateNeedProduct \n");
                Need_1_0 beanRemote = lookupService();

                NeedProduct testNewInstance = getNeedProductInstance();

                System.out.println("NeedProduct input " + testNewInstance + "\n");
                NeedProduct testNewResult = beanRemote
                                .updateNeedProduct(testNewInstance);

                assertNotNull(testNewResult);

                storeNeedProductInstance(testNewResult);
                System.out.println("NeedProduct " + testNewResult);
        }
       
        public NeedProduct getNeedProductInstance() {

                if (needProductInstance != null) return needProductInstance;
                         needInstance.getNeedProduct().get(0).setCreatedByPID("A134678");
                return needInstance.getNeedProduct().get(0);
        }
       
        public void storeNeedProductInstance(
                        NeedProduct instance) {
                        needProductInstance = instance;        
        }
       
3. test Methods for getNeed
        public void test_getNeed() throws Exception {
                System.out.println("start test_getNeed \n");
                Need_1_0 beanRemote = lookupService();
                Need testInstance = getNeedInstance();
                GetNeed_Parameters getNeed_Parameters = provide_GetNeed_Parameters();
                Need testResult = beanRemote
                                .getNeed(getNeed_Parameters.id);
                assertNotNull(testResult);
                assertNotNull(testResult.getUid());
                if (testInstance.getBUID() != null)
                        assertEquals(testInstance.getBUID(), testResult.getBUID());
                if (testInstance.getPartner() != null)
                        assertEquals(testInstance.getPartner(), testResult.getPartner());
                if (testInstance.getComment() != null)
                        assertEquals(testInstance.getComment(), testResult.getComment());
                if (testInstance.getType() != null)
                        assertEquals(testInstance.getType(), testResult.getType());
                if (testInstance.getStatus() != null)
                        assertEquals(testInstance.getStatus(), testResult.getStatus());

                storeNeedInstance(testResult);
                System.out.println("end test_getNeed \n");
        }
       
        public GetNeed_Parameters provide_GetNeed_Parameters() {
                GetNeed_Parameters x = new GetNeed_Parameters();
                x.id = needInstance.getUid();
                return x;
        }      

And here are the SQL statements in the sequence as they appear in the logs.
 
INSERT INTO XXXX.SNEED_NEED_VAMI#00 (XMI_INSTANCE_TGUID, XMU_INSTANCE_LIFECYCLE_STATUS, XMU_CREATED_BY_PID, XMU_NEED_STATUS, XMD_CREATED_AT_TSMP, XMI_PARTNER_TGUID, XMU_NEED_COMMENT, XMU_CURRENT_OWNING_BUID, XMU_NEED_TYPE, XMU_INSTANCE_MUT_SEQNR) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
 bind => [BF18D9430A8F440A97FAE783E9E4A8A2, 2, A448579, CCC, null, 717B452D7B2B43BDE04400144FEBBD1C, DDD1, 0012, AAA, 1]
 
INSERT INTO XXXX.SNEED_NEEDP_VAMI#00 (XMI_INSTANCE_TGUID, XMU_INSTANCE_LIFECYCLE_STATUS, XMU_CREATED_BY_PID, XMD_CREATED_AT_TSMP, XMI_NEED_PRODUCT_CD, XMU_INSTANCE_MUT_SEQNR, XMI_NEED_TGUID) VALUES (?, ?, ?, ?, ?, ?, ?)
 bind => [A78E9E5B2901458B8D0DC41435A22CD0, 2, A448579, null, P2, 1, BF18D9430A8F440A97FAE783E9E4A8A2]
 
SELECT XMI_INSTANCE_TGUID, XMU_INSTANCE_LIFECYCLE_STATUS, XMU_CREATED_BY_PID, XMU_NEED_STATUS, XMD_CREATED_AT_TSMP, XMI_PARTNER_TGUID, XMU_NEED_COMMENT, XMU_CURRENT_OWNING_BUID, XMU_NEED_TYPE, XMU_INSTANCE_MUT_SEQNR FROM XXXX.SNEED_NEED_VAMI#00 WHERE (XMI_INSTANCE_TGUID = ?)
 bind => [BF18D9430A8F440A97FAE783E9E4A8A2]
 
SELECT XMI_INSTANCE_TGUID, XMU_INSTANCE_LIFECYCLE_STATUS, XMU_CREATED_BY_PID, XMD_CREATED_AT_TSMP, XMI_NEED_PRODUCT_CD, XMU_INSTANCE_MUT_SEQNR, XMI_NEED_TGUID FROM XXXX.SNEED_NEEDP_VAMI#00 WHERE (XMI_NEED_TGUID = ?)
 bind => [[B@1662318]
 
SELECT XMI_INSTANCE_TGUID, XMU_INSTANCE_LIFECYCLE_STATUS, XMU_CREATED_BY_PID, XMU_NEED_STATUS, XMD_CREATED_AT_TSMP, XMI_PARTNER_TGUID, XMU_NEED_COMMENT, XMU_CURRENT_OWNING_BUID, XMU_NEED_TYPE, XMU_INSTANCE_MUT_SEQNR FROM XXXX.SNEED_NEED_VAMI#00 WHERE (XMI_INSTANCE_TGUID = ?)
 bind => [[B@8a3bf2]
 

UPDATE XXXX.SNEED_NEEDP_VAMI#00 SET XMU_INSTANCE_LIFECYCLE_STATUS = ?, XMU_INSTANCE_MUT_SEQNR = ? WHERE ((XMI_INSTANCE_TGUID = ?) AND (XMU_INSTANCE_MUT_SEQNR = ?))
 bind => [7, 2, A78E9E5B2901458B8D0DC41435A22CD0, 1]
 
SELECT XMI_INSTANCE_TGUID, XMU_INSTANCE_LIFECYCLE_STATUS, XMU_CREATED_BY_PID, XMD_CREATED_AT_TSMP, XMI_NEED_PRODUCT_CD, XMU_INSTANCE_MUT_SEQNR, XMI_NEED_TGUID FROM XXXX.SNEED_NEEDP_VAMI#00 WHERE (XMI_INSTANCE_TGUID = ?)
 bind => [A78E9E5B2901458B8D0DC41435A22CD0]
 
SELECT XMI_INSTANCE_TGUID, XMU_INSTANCE_LIFECYCLE_STATUS, XMU_CREATED_BY_PID, XMU_NEED_STATUS, XMD_CREATED_AT_TSMP, XMI_PARTNER_TGUID, XMU_NEED_COMMENT, XMU_CURRENT_OWNING_BUID, XMU_NEED_TYPE, XMU_INSTANCE_MUT_SEQNR FROM XXXX.SNEED_NEED_VAMI#00 WHERE (XMI_INSTANCE_TGUID = ?)
 bind => [[B@6faf61]
 
SELECT XMI_INSTANCE_TGUID, XMU_INSTANCE_LIFECYCLE_STATUS, XMU_CREATED_BY_PID, XMD_CREATED_AT_TSMP, XMI_NEED_PRODUCT_CD, XMU_INSTANCE_MUT_SEQNR, XMI_NEED_TGUID FROM XXXX.SNEED_NEEDP_VAMI#00 WHERE (XMI_NEED_TGUID = ?)
 bind => [[B@63359c]
 
 
Another point to note is, this behaviour is reproducible even in application and not limited to tests. And I think if you see the code in GenericDAOJPAImpl, it refreshes the entity after it is merged and return the same.

public T update(T entity) {

entity = entityManager.merge(entity);

entityManager.flush();

entityManager.refresh(entity);

return entity;

}



Thanks & Regards, Mahipal

-----Original Message-----
From: eclipselink-users-bounces@xxxxxxxxxxx [mailto:eclipselink-users-bounces@xxxxxxxxxxx] On Behalf Of James Sutherland
Sent: Tuesday, March 09, 2010 4:38 PM
To: eclipselink-users@xxxxxxxxxxx
Subject: Re: [eclipselink-users] Eclipselink Shared Cache duplicate entities


Could you include the SQL log, and the code for your test methods.

It seems you might be corrupting your object clones.  My guess would be you
are keeping the new Need on the test client which does not have any assign
ids, then every time you merge() it, you are adding new NeedProducts, as
their id is null.  You need to return the inserted/updated objects back to
the client.



Mahipal wrote:
>
> 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
>
> _______________________________________________
> eclipselink-users mailing list
> eclipselink-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
>
>


-----
http://wiki.eclipse.org/User:James.sutherland.oracle.com James Sutherland
http://www.eclipse.org/eclipselink/
 EclipseLink ,  http://www.oracle.com/technology/products/ias/toplink/
TopLink
Wiki:  http://wiki.eclipse.org/EclipseLink EclipseLink ,
http://wiki.oracle.com/page/TopLink TopLink
Forums:  http://forums.oracle.com/forums/forum.jspa?forumID=48 TopLink ,
http://www.nabble.com/EclipseLink-f26430.html EclipseLink
Book:  http://en.wikibooks.org/wiki/Java_Persistence Java Persistence
--
View this message in context: http://old.nabble.com/Eclipselink-Shared-Cache-duplicate-entities-tp27793000p27837418.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.

_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users


Back to the top