2010-10-20 2 views
7

Ich habe eine Frage, die ich denke, sollte ziemlich häufig sein, aber ich kann keine Antwort finden.Hibernate @ManyToMany bidirektionale eifrig holen

Ich habe 2 Objekte: Gruppe und Benutzer. Meine Klassen in etwa so aussehen:

class Group 
{ 
    @ManyToMany(fetch = FetchType.EAGER) 
    List<User> users; 
} 

class User 
{ 
    @ManyToMany(fetch = FetchType.EAGER) 
    List<Group> groups; 
} 

Nun, wenn ich versuche, einen Benutzer aus der Datenbank zu erhalten bringen sie alle ihre Gruppen und alle Gruppen bringen alle Benutzer und so weiter. Schließlich bekomme ich eine stackoverflow-Ausnahme.

Wie kann ich dieses Problem lösen und habe weiterhin meine bidirektionale Zuordnung und die Möglichkeit, die Objekte in den Listen zu erreichen?

Antwort

8

Haben Sie das gleiche Problem, wenn Sie eine der Seiten des bidirektionalen assocation machen die besitzen Seite des Vereins mit dem mappedBy Attribut (das sollten Sie verwenden sowieso)? Wie folgt aus:

@Entity public class Group { 
    ... 
    @ManyToMany(fetch = FetchType.EAGER, mappedBy="groups") 
    List<User> users; 
} 

@Entity public class User { 
    ... 
    @ManyToMany(fetch = FetchType.EAGER) 
    List<Group> groups; 
} 

Update: Ich kann keine Beweise dafür finden, dass die Verwendung von EAGER Holen auf beiden Seiten einer bidirektionalen Vereinigung verboten ist und AFAIK, gibt es keine Erwähnung einer solchen Beschränkung in der Hibernate Dokumentation und/oder die JPA-Spezifikation.

Eigentlich nach this comment von Emmanuel Bernard zu einer (irgendwie ähnlich) Ausgabe:

LAZY oder EAGER soll in der Code-Basis zu einer Endlosschleife Ausgabe orthogonal sein. Hibernate weiß, wie zyklische Graphen

Für mich zu handhaben, die oben ziemlich klar ist, sollte Hibernate Lage sein, Ihre Zuordnung zu behandeln (wie ich in einem Kommentar erwähnt) und ich würde jedes widersprüchliches Verhalten als eine zu betrachten versucht sein, Fehler.

Wenn Sie einen Testfall zur Verfügung stellen können, um das Problem zu reproduzieren, wäre mein Vorschlag, ein Problem zu öffnen.

+0

ja. das Gleiche passiert. Ich kann verstehen, dass es Sinn macht b/c Hibernate muss alle Listenobjekte für jede Liste bringen und es ist eine Endlosschleife. Meine Frage ist, ob es möglich ist, die Tiefe zu begrenzen, die Hibernate bringt (etwas wie fetch_max_depth, aber für viele-zu-viele). – refaelos

+0

@Rafa Eigentlich würde ich erwarten, dass Hibernate den Zyklus erkennt und das passende tut (aber ich habe mir nicht die Zeit genommen, das zu testen). Auf der anderen Seite kann ich nicht sagen, dass das Aufladen beider Seiten eines Viele-zu-Viele-Looks eine gute Idee ist. –

0

Hibernate funktioniert, wenn es versucht, alles, was es braucht, eifrig zu holen. Bei der Modellierung von Objekten muss der Ruhezustand berücksichtigt werden, sodass keine Schleifen- und Stackoverflow-Ausnahmen auftreten.

Was ich getan habe, ist eine Seite der Beziehung zu entfernen. Sie können entscheiden, ob Sie diese Seite entfernen oder lassen und die andere Seite als Eigentümer definieren möchten. Sie müssen auch das eifrige Holen von dieser Seite entfernen.

Es wäre schön, wenn Hibernate einen Mechanismus für die Festlegung der Tiefe des Abrufs in Viele-zu-viele-Beziehungen geben könnte.

0

Vielleicht möchten Sie die Eigenschaft "hibernate.max_fetch_depth" auf 3 setzen, um den Eager-Abruf zu begrenzen.

Verwandte Themen