如果我在DataModel中具有雙向關係,那麼我的應用程序有責任將引用保持在Java代碼中。JPA雙向關係
這樣做的最好方法是什麼?
例如bidir。 1:A和B.
@Entity
class A {
@ManyToOne
private B b;
}
@Entity
class B {
@OneToMany(mappedBy="b")
private Collection<A> as;
}
如果我說B.addA(b)本不讓變量A中的B點至i添加的參考之間的N個關係。 如果我打電話給A.setB(b),這不會將b的引用添加到B中的集合中。
一種可能的方法是在我的應用程序代碼中調用setB AND addA。
其他posibility是寫這樣的組A(..)方法:
public setB(B b) {
this.b = b;
if(!b.contains(this) {
b.add(this);
}
}
public addA(A a) {
if(!as.conatains(a)) {
as.add(a);
}
a.setB(this);
}
但是這有時會拋出一些例外,如:
org.hibernate.LazyInitializationException: illegal access to loading collection
我猜是因爲框架來電某點這個setMethod並且想要加載「this」引用...?!?有人可以解釋爲什麼會發生這種情況嗎? 什麼是保證我在我的java代碼中有乾淨的bidrectional關係的方式?
THX
UPDATE: 這裏是原代碼:
@Entity
class Cluster{
private Grid grid
//someother fields
@ManyToOne
public Grid getGrid() {
return grid;
}
public void setGrid(Grid grid) {
this.grid = grid;
if(!grid.getClusters().contains(this)) { //HERE AN EXCEPTION IS THROWN
grid.addCluster(this);
}
}
}
@Entity
class Grid {
private Collection<Cluster> clusters = new ArrayList<Cluster>();
//some other fields
@OneToMany(mappedBy = "grid", cascade = CascadeType.PERSIST, orphanRemoval = true)
public Collection<Cluster> getClusters() {
return clusters;
}
public void setClusters(Collection<Cluster> clusters) {
this.clusters = clusters;
}
public void addCluster(Cluster c) {
this.clusters.add(c);
c.setGrid(this);
}
}
在我的查詢之一,我得到它說,setGrid方法IST內部出了差錯例外...如果我刪除線一切都很好..但後來我沒有我的雙向...:/
堆棧跟蹤:
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: Exception occurred inside setter of dst1.model.Cluster.grid
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1214)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1147)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:255)
at dst1.Main.dst02b(Main.java:828)
at dst1.Main.main(Main.java:38)
Caused by: org.hibernate.PropertyAccessException: Exception occurred inside setter of dst1.model.Cluster.grid
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:89)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:583)
at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:229)
at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3822)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:152)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982)
at org.hibernate.loader.Loader.doQuery(Loader.java:857)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.loadEntity(Loader.java:2037)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:86)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:76)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3268)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:496)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:477)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:227)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1090)
at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1038)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:630)
at org.hibernate.type.EntityType.resolve(EntityType.java:438)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:139)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982)
at org.hibernate.loader.Loader.doQuery(Loader.java:857)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.doList(Loader.java:2533)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
at org.hibernate.loader.Loader.list(Loader.java:2271)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:452)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1268)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:246)
... 2 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:66)
... 35 more
Caused by: org.hibernate.PropertyAccessException: Exception occurred inside setter of dst1.model.Cluster.grid
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:89)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:583)
at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:229)
at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3822)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:152)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:982)
at org.hibernate.loader.Loader.doQuery(Loader.java:857)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
at org.hibernate.loader.Loader.loadCollection(Loader.java:2166)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:62)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:627)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1863)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:369)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.AbstractPersistentCollection.readElementExistence(AbstractPersistentCollection.java:167)
at org.hibernate.collection.PersistentBag.contains(PersistentBag.java:262)
at dst1.model.Cluster.setGrid(Cluster.java:114)
... 40 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:66)
... 57 more
Caused by: org.hibernate.LazyInitializationException: illegal access to loading collection
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:366)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.AbstractPersistentCollection.readElementExistence(AbstractPersistentCollection.java:167)
at org.hibernate.collection.PersistentBag.contains(PersistentBag.java:262)
at dst1.model.Cluster.setGrid(Cluster.java:114)
... 62 more
還沒有你反饋? – 2012-04-02 18:26:43
嗨,非常感謝您的幫助,但不幸的是,這並沒有解決問題。每當我想從一個相關實體的set/add方法中獲得另一個實體的集合時,我得到這個LazyInitializationException:/我將嘗試拆分我的解決方案,看看我能得到更多細節爲什麼會發生這種情況:(謝謝你在尋求幫助 – Moonlit 2012-04-02 20:46:43
也許你應該在Hibernate論壇上提問,他們會更好地瞭解實現的內部結構 – 2012-04-02 21:10:41