You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Kuthiala, Amit" <Am...@bose.com> on 2008/09/19 16:52:15 UTC

Openjpa does not lazy fetch in OneToMany

 I think what I am seeing might be a bug in openJPA. JPA is thinking it is an orphaned record but it does exist.I think it is going against the wrong table. I have an abstract superclass (Party) which is extended by Site and Store class. Site has one or more Stores and Store maps to one site. So there is a OneToMany relationship between them.

In my test cases I am creating a Store and passing in an existing site. (Code below). When I try to lazy fetch the Stores for a Site it works but If I try to get the site for a Store it gives me the message below.

Detected possible orphaned reference to deleted object "com.bose.beans.Store-1502" in "com.bose.beans.Store.site".


Looking at the console it seems it is trying to go against the Store table when it should really be going against the Site table. Is openJPA getting confused because both Site and Store have the same Primary key PartyId from the superclass Party. Store has a field called SiteId that is a foreign key into Site.

578        TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t 16749745, conn 1646156> executing prepstmnt 17860391 SELECT t0.PartyType, t0.version, t0.archiveStatus, t0.createDate, t0.status, t1.siteId, t1.storeDescription, t1.storeName FROM Store t1 INNER JOIN TranParty t0 ON t1.partyId = t0.partyId WHERE t1.partyId = ? [params=(long) 1502]

Here 1502 is a PartyId for Site but JPA is trying to find it in Store table.

-Amit

Details of the implementation and snapshots of classes, TestCases and Console log.

I have this hierarchy of classes. TranParty is the base class for both Site and Store. The Site has OnetoMany relationship with Store.




[cid:image001.gif@01C91A45.C647CE30]

@Entity@Table(name = "Site")
@DiscriminatorValue("Site")
public class Site  extends Party implements java.io.Serializable {

      private static final long serialVersionUID = 1L;
      private String SiteName;
      private String SiteDescription;
      private List<Store> stores;

@OneToMany(mappedBy="site", cascade=CascadeType.ALL, fetch=FetchType.LAZY, targetEntity=Store.class)
      public List<Store> getStores() {
            return stores;
      }
}

@Entity@Table(name = "Store")
@DiscriminatorValue("Store")
public class Store extends Party implements java.io.Serializable {

      private static final long serialVersionUID = 1L;
      //private SystemSubscriber systemSubscriber;
      private String StoreName;
      private String StoreDescription;
      private Site site;
      private Long SiteId;

      @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, targetEntity=Site.class)
      @JoinColumn(name = "Store.SiteId", referencedColumnName="site.PartyId", nullable = false, insertable = true, updatable = true)
      public Site getSite() {
            return site;
      }
}

I am testing thorugh these methods. First creating a new Store with a Site and then testing if the Store can lazy load the Site. Lazy loading for Store from Site works fine. I get this error in the console.

578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t 16749745, conn 1541717> executing prepstmnt 17726622 SELECT t0.PartyType, t0.version, t0.archiveStatus, t0.createDate, t0.status, t1.siteId, t1.storeDescription, t1.storeName FROM Store t1 INNER JOIN TranParty t0 ON t1.partyId = t0.partyId WHERE t1.partyId = ? [params=(long) 1552]
578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t 16749745, conn 1541717> [0 ms] spent
578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.JDBC - <t 16749745, conn 1541717> [0 ms] close
578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t 16749745, conn 1646156> executing prepstmnt 17860391 SELECT t0.PartyType, t0.version, t0.archiveStatus, t0.createDate, t0.status, t1.siteId, t1.storeDescription, t1.storeName FROM Store t1 INNER JOIN TranParty t0 ON t1.partyId = t0.partyId WHERE t1.partyId = ? [params=(long) 1502] - This SQL is executed when it tries to lazy fetch the Site. It looks like the query is wrong because it is going against the Store table instead of the Site table. The PartyId it is using is for the Site.
594  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t 16749745, conn 1646156> [16 ms] spent
594  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.JDBC - <t 16749745, conn 1646156> [0 ms] close
594  TestBosePersistenceUnit  WARN   [main] openjpa.Runtime - Detected possible orphaned reference to deleted object "com.bose.beans.Store-1502" in "com.bose.beans.Store.site".




@Test
      public void createNewStore() {
            em.getTransaction().begin();
            Store store = new Store();
            store.setStoreDescription("storeDescription");
            store.setStoreName("storeName");
            store.setStatus("1");
            store.setArchiveStatus("1");
            store.setCreateDate(new Date());

            store.setSiteId(TestCaseHelper.getSiteIdCreated());

            Site site = em.find(Site.class, TestCaseHelper.getSiteIdCreated());
            //store.setSiteId(site.getSiteId());
            store.setSite(site);
            List<Store> stores = new ArrayList<Store>();
            stores.add(store);
            site.setStores(stores);

            em.persist(store);
            em.getTransaction().commit();

            em.refresh(store);
            TestCaseHelper.setStoreIdCreated(store.getPartyId());
            store = em.find(Store.class, store.getPartyId());
            assertNotNull(store);
      }

@Test
      public void getStoreWithSite() {
            Store store = em.find(Store.class, TestCaseHelper.getStoreIdCreated());

            assertNotNull(store);

            Site site = store.getSite();
            assertNotNull(site);

      }



Re: Openjpa does not lazy fetch in OneToMany

Posted by Sandhya Kishore <tu...@yahoo.com>.
Hi Amit,
 
      If you can send the abstract class "Party" also it would be great.

Thanks
Sandhya Turaga

--- On Thu, 11/20/08, lemitja <mi...@uni-mb.si> wrote:
From: lemitja <mi...@uni-mb.si>
Subject: Re: Openjpa does not lazy fetch in OneToMany
To: users@openjpa.apache.org
Date: Thursday, November 20, 2008, 11:26 AM

I've noticed the same problem and can confirm bug in OpenJPA 1.2. It is not
limited to lazy fetches. The identity of the entity is incorrectly
determined in the case of polymorphic relation, consequently wrong SQL is
generated to retrieve data, which then results in orphaned message. The 
reference type is resolved to the same type as the owner relation class. In
your example the identity should be "com.bose.beans.Site-1502""
instead of
"com.bose.beans.Store-1502"

If this happens for the leaf classes, possible workaround is to use
@Nonpolymorphic annotation on @ManyToOne part of the relation.

 

Kuthiala, Amit wrote:
> 
>  I think what I am seeing might be a bug in openJPA. JPA is thinking it is
> an orphaned record but it does exist.I think it is going against the wrong
> table. I have an abstract superclass (Party) which is extended by Site and
> Store class. Site has one or more Stores and Store maps to one site. So
> there is a OneToMany relationship between them.
> 
> In my test cases I am creating a Store and passing in an existing site.
> (Code below). When I try to lazy fetch the Stores for a Site it works but
> If I try to get the site for a Store it gives me the message below.
> 
> Detected possible orphaned reference to deleted object
> "com.bose.beans.Store-1502" in
"com.bose.beans.Store.site".
> 
> 
> Looking at the console it seems it is trying to go against the Store table
> when it should really be going against the Site table. Is openJPA getting
> confused because both Site and Store have the same Primary key PartyId
> from the superclass Party. Store has a field called SiteId that is a
> foreign key into Site.
> 
> 578        TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1646156> executing prepstmnt 17860391 SELECT
t0.PartyType,
> t0.version, t0.archiveStatus, t0.createDate, t0.status, t1.siteId,
> t1.storeDescription, t1.storeName FROM Store t1 INNER JOIN TranParty t0 ON
> t1.partyId = t0.partyId WHERE t1.partyId = ? [params=(long) 1502]
> 
> Here 1502 is a PartyId for Site but JPA is trying to find it in Store
> table.
> 
> -Amit
> 
> Details of the implementation and snapshots of classes, TestCases and
> Console log.
> 
> I have this hierarchy of classes. TranParty is the base class for both
> Site and Store. The Site has OnetoMany relationship with Store.
> 
> 
> 
> 
> [cid:image001.gif@01C91A45.C647CE30]
> 
> @Entity@Table(name = "Site")
> @DiscriminatorValue("Site")
> public class Site  extends Party implements java.io.Serializable {
> 
>       private static final long serialVersionUID = 1L;
>       private String SiteName;
>       private String SiteDescription;
>       private List<Store> stores;
> 
> @OneToMany(mappedBy="site", cascade=CascadeType.ALL,
fetch=FetchType.LAZY,
> targetEntity=Store.class)
>       public List<Store> getStores() {
>             return stores;
>       }
> }
> 
> @Entity@Table(name = "Store")
> @DiscriminatorValue("Store")
> public class Store extends Party implements java.io.Serializable {
> 
>       private static final long serialVersionUID = 1L;
>       //private SystemSubscriber systemSubscriber;
>       private String StoreName;
>       private String StoreDescription;
>       private Site site;
>       private Long SiteId;
> 
>       @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY,
> targetEntity=Site.class)
>       @JoinColumn(name = "Store.SiteId",
> referencedColumnName="site.PartyId", nullable = false,
insertable = true,
> updatable = true)
>       public Site getSite() {
>             return site;
>       }
> }
> 
> I am testing thorugh these methods. First creating a new Store with a Site
> and then testing if the Store can lazy load the Site. Lazy loading for
> Store from Site works fine. I get this error in the console.
> 
> 578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1541717> executing prepstmnt 17726622 SELECT
t0.PartyType,
> t0.version, t0.archiveStatus, t0.createDate, t0.status, t1.siteId,
> t1.storeDescription, t1.storeName FROM Store t1 INNER JOIN TranParty t0 ON
> t1.partyId = t0.partyId WHERE t1.partyId = ? [params=(long) 1552]
> 578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1541717> [0 ms] spent
> 578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.JDBC - <t
> 16749745, conn 1541717> [0 ms] close
> 578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1646156> executing prepstmnt 17860391 SELECT
t0.PartyType,
> t0.version, t0.archiveStatus, t0.createDate, t0.status, t1.siteId,
> t1.storeDescription, t1.storeName FROM Store t1 INNER JOIN TranParty t0 ON
> t1.partyId = t0.partyId WHERE t1.partyId = ? [params=(long) 1502] - This
> SQL is executed when it tries to lazy fetch the Site. It looks like the
> query is wrong because it is going against the Store table instead of the
> Site table. The PartyId it is using is for the Site.
> 594  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1646156> [16 ms] spent
> 594  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.JDBC - <t
> 16749745, conn 1646156> [0 ms] close
> 594  TestBosePersistenceUnit  WARN   [main] openjpa.Runtime - Detected
> possible orphaned reference to deleted object
"com.bose.beans.Store-1502"
> in "com.bose.beans.Store.site".
> 
> 
> 
> 
> @Test
>       public void createNewStore() {
>             em.getTransaction().begin();
>             Store store = new Store();
>             store.setStoreDescription("storeDescription");
>             store.setStoreName("storeName");
>             store.setStatus("1");
>             store.setArchiveStatus("1");
>             store.setCreateDate(new Date());
> 
>             store.setSiteId(TestCaseHelper.getSiteIdCreated());
> 
>             Site site = em.find(Site.class,
> TestCaseHelper.getSiteIdCreated());
>             //store.setSiteId(site.getSiteId());
>             store.setSite(site);
>             List<Store> stores = new ArrayList<Store>();
>             stores.add(store);
>             site.setStores(stores);
> 
>             em.persist(store);
>             em.getTransaction().commit();
> 
>             em.refresh(store);
>             TestCaseHelper.setStoreIdCreated(store.getPartyId());
>             store = em.find(Store.class, store.getPartyId());
>             assertNotNull(store);
>       }
> 
> @Test
>       public void getStoreWithSite() {
>             Store store = em.find(Store.class,
> TestCaseHelper.getStoreIdCreated());
> 
>             assertNotNull(store);
> 
>             Site site = store.getSite();
>             assertNotNull(site);
> 
>       }
> 
> 
> 
> 

-- 
View this message in context:
http://n2.nabble.com/Openjpa-does-not-lazy-fetch-in-OneToMany-tp1101139p1558514.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.




      

Re: Openjpa does not lazy fetch in OneToMany

Posted by lemitja <mi...@uni-mb.si>.
I've noticed the same problem and can confirm bug in OpenJPA 1.2. It is not
limited to lazy fetches. The identity of the entity is incorrectly
determined in the case of polymorphic relation, consequently wrong SQL is
generated to retrieve data, which then results in orphaned message. The 
reference type is resolved to the same type as the owner relation class. In
your example the identity should be "com.bose.beans.Site-1502"" instead of
"com.bose.beans.Store-1502"

If this happens for the leaf classes, possible workaround is to use
@Nonpolymorphic annotation on @ManyToOne part of the relation.

 

Kuthiala, Amit wrote:
> 
>  I think what I am seeing might be a bug in openJPA. JPA is thinking it is
> an orphaned record but it does exist.I think it is going against the wrong
> table. I have an abstract superclass (Party) which is extended by Site and
> Store class. Site has one or more Stores and Store maps to one site. So
> there is a OneToMany relationship between them.
> 
> In my test cases I am creating a Store and passing in an existing site.
> (Code below). When I try to lazy fetch the Stores for a Site it works but
> If I try to get the site for a Store it gives me the message below.
> 
> Detected possible orphaned reference to deleted object
> "com.bose.beans.Store-1502" in "com.bose.beans.Store.site".
> 
> 
> Looking at the console it seems it is trying to go against the Store table
> when it should really be going against the Site table. Is openJPA getting
> confused because both Site and Store have the same Primary key PartyId
> from the superclass Party. Store has a field called SiteId that is a
> foreign key into Site.
> 
> 578        TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1646156> executing prepstmnt 17860391 SELECT t0.PartyType,
> t0.version, t0.archiveStatus, t0.createDate, t0.status, t1.siteId,
> t1.storeDescription, t1.storeName FROM Store t1 INNER JOIN TranParty t0 ON
> t1.partyId = t0.partyId WHERE t1.partyId = ? [params=(long) 1502]
> 
> Here 1502 is a PartyId for Site but JPA is trying to find it in Store
> table.
> 
> -Amit
> 
> Details of the implementation and snapshots of classes, TestCases and
> Console log.
> 
> I have this hierarchy of classes. TranParty is the base class for both
> Site and Store. The Site has OnetoMany relationship with Store.
> 
> 
> 
> 
> [cid:image001.gif@01C91A45.C647CE30]
> 
> @Entity@Table(name = "Site")
> @DiscriminatorValue("Site")
> public class Site  extends Party implements java.io.Serializable {
> 
>       private static final long serialVersionUID = 1L;
>       private String SiteName;
>       private String SiteDescription;
>       private List<Store> stores;
> 
> @OneToMany(mappedBy="site", cascade=CascadeType.ALL, fetch=FetchType.LAZY,
> targetEntity=Store.class)
>       public List<Store> getStores() {
>             return stores;
>       }
> }
> 
> @Entity@Table(name = "Store")
> @DiscriminatorValue("Store")
> public class Store extends Party implements java.io.Serializable {
> 
>       private static final long serialVersionUID = 1L;
>       //private SystemSubscriber systemSubscriber;
>       private String StoreName;
>       private String StoreDescription;
>       private Site site;
>       private Long SiteId;
> 
>       @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY,
> targetEntity=Site.class)
>       @JoinColumn(name = "Store.SiteId",
> referencedColumnName="site.PartyId", nullable = false, insertable = true,
> updatable = true)
>       public Site getSite() {
>             return site;
>       }
> }
> 
> I am testing thorugh these methods. First creating a new Store with a Site
> and then testing if the Store can lazy load the Site. Lazy loading for
> Store from Site works fine. I get this error in the console.
> 
> 578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1541717> executing prepstmnt 17726622 SELECT t0.PartyType,
> t0.version, t0.archiveStatus, t0.createDate, t0.status, t1.siteId,
> t1.storeDescription, t1.storeName FROM Store t1 INNER JOIN TranParty t0 ON
> t1.partyId = t0.partyId WHERE t1.partyId = ? [params=(long) 1552]
> 578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1541717> [0 ms] spent
> 578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.JDBC - <t
> 16749745, conn 1541717> [0 ms] close
> 578  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1646156> executing prepstmnt 17860391 SELECT t0.PartyType,
> t0.version, t0.archiveStatus, t0.createDate, t0.status, t1.siteId,
> t1.storeDescription, t1.storeName FROM Store t1 INNER JOIN TranParty t0 ON
> t1.partyId = t0.partyId WHERE t1.partyId = ? [params=(long) 1502] - This
> SQL is executed when it tries to lazy fetch the Site. It looks like the
> query is wrong because it is going against the Store table instead of the
> Site table. The PartyId it is using is for the Site.
> 594  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.SQL - <t
> 16749745, conn 1646156> [16 ms] spent
> 594  TestBosePersistenceUnit  TRACE  [main] openjpa.jdbc.JDBC - <t
> 16749745, conn 1646156> [0 ms] close
> 594  TestBosePersistenceUnit  WARN   [main] openjpa.Runtime - Detected
> possible orphaned reference to deleted object "com.bose.beans.Store-1502"
> in "com.bose.beans.Store.site".
> 
> 
> 
> 
> @Test
>       public void createNewStore() {
>             em.getTransaction().begin();
>             Store store = new Store();
>             store.setStoreDescription("storeDescription");
>             store.setStoreName("storeName");
>             store.setStatus("1");
>             store.setArchiveStatus("1");
>             store.setCreateDate(new Date());
> 
>             store.setSiteId(TestCaseHelper.getSiteIdCreated());
> 
>             Site site = em.find(Site.class,
> TestCaseHelper.getSiteIdCreated());
>             //store.setSiteId(site.getSiteId());
>             store.setSite(site);
>             List<Store> stores = new ArrayList<Store>();
>             stores.add(store);
>             site.setStores(stores);
> 
>             em.persist(store);
>             em.getTransaction().commit();
> 
>             em.refresh(store);
>             TestCaseHelper.setStoreIdCreated(store.getPartyId());
>             store = em.find(Store.class, store.getPartyId());
>             assertNotNull(store);
>       }
> 
> @Test
>       public void getStoreWithSite() {
>             Store store = em.find(Store.class,
> TestCaseHelper.getStoreIdCreated());
> 
>             assertNotNull(store);
> 
>             Site site = store.getSite();
>             assertNotNull(site);
> 
>       }
> 
> 
> 
> 

-- 
View this message in context: http://n2.nabble.com/Openjpa-does-not-lazy-fetch-in-OneToMany-tp1101139p1558514.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.