Wenn ich eine bidirektionale Beziehung in meinem DataModel habe, liegt es in meiner Verantwortung, die Referenzen im Java-Code aktuell zu halten.JPA bidirektionale Beziehungen
Was ist der beste Weg, dies zu tun?
Zum Beispiel ein bidir. 1: n-Beziehung zwischen A und B.
@Entity
class A {
@ManyToOne
private B b;
}
@Entity
class B {
@OneToMany(mappedBy="b")
private Collection<A> as;
}
Wenn ich sage B.addA (b) dies nicht die Variable b in einem Punkt die Referenz wird lassen i hinzugefügt. Und wenn ich A.setB (b) aufrufen, fügt dies keine Referenz von b zur Sammlung in B hinzu.
Eine Möglichkeit wäre, setB UND addA in meinem Anwendungscode aufzurufen.
Die anderen posibility wären die setA (..) Methode wie folgt zu schreiben:
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);
}
aber das wirft manchmal einige Ausnahmen wie:
org.hibernate.LazyInitializationException: illegal access to loading collection
ich denke, da das Framework ruft an Irgendeinem dieser setMethod und möchte die "diese" Referenz laden ...?!? Kann mir jemand erklären, warum das passiert? Und was ist der Weg zu gehen, um sicherzustellen, dass ich saubere bidirektionale Beziehungen in meinem Java-Code habe?
thx
UPDATE: hier ist der ursprüngliche Code:
@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);
}
}
In einem meiner Abfragen ich die Ausnahme erhalten, die besagt, dass etwas in der setGrid Methode ist falsch ... Wenn Ich entferne die Zeilen alles ist in Ordnung .. aber dann habe ich nicht meine Bidirektionale ...:/
Der Stacktrace:
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
hast du noch kein feedback? –
Hallo und vielen Dank für Ihre Hilfe, aber leider hat es das Problem nicht gelöst. Wann immer ich die Sammlung einer anderen Entität aus einer set/add -Methode einer verwandten Entität herausholen möchte, bekomme ich diese LazyInitializationException:/Ich werde versuchen, meine Lösung auseinander zu nehmen und zu sehen, ob ich weitere Details bekommen kann, warum das passiert :(danke Sie für Ihre Hilfe – Moonlit
vielleicht sollten Sie im Hibernate Forum fragen, werden sie besser die Interna der Implementierung wissen. –