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.