615 Stimmen

Hibernate löst MultipleBagFetchException aus - kann nicht gleichzeitig mehrere Beutel abrufen

Hibernate löst diese Ausnahme bei der Erstellung der SessionFactory aus:

org.hibernate.loader.MultipleBagFetchException: kann nicht mehrere Taschen gleichzeitig abrufen

Dies ist mein Testfall:

Elternteil.java

@Entity
public Parent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 // @IndexColumn(name="INDEX_COL") if I had this the problem solve but I retrieve more children than I have, one child is null.
 private List<Child> children;

}

Kind.java

@Entity
public Child {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @ManyToOne
 private Parent parent;

}

Was ist mit diesem Problem? Was kann ich tun?


EDITAR

OK, das Problem, das ich habe, ist, dass eine andere "übergeordnete" Entität innerhalb meiner übergeordneten ist, mein wirkliches Verhalten ist dies:

Elternteil.java

@Entity
public Parent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @ManyToOne
 private AnotherParent anotherParent;

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 private List<Child> children;

}

AnotherParent.java

@Entity
public AnotherParent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 private List<AnotherChild> anotherChildren;

}

Hibernate mag keine zwei Sammlungen mit FetchType.EAGER aber das scheint ein Fehler zu sein, ich mache keine ungewöhnlichen Dinge...

Entfernen von FetchType.EAGER de Parent o AnotherParent löst das Problem, aber ich brauche es, also ist die wirkliche Lösung die Verwendung von @LazyCollection(LazyCollectionOption.FALSE) anstelle von FetchType (Dank an Bozho für die Lösung).

2 Stimmen

Ich würde fragen, welche SQL-Abfrage Sie zu erstellen hoffen, die zwei separate Sammlungen gleichzeitig abruft? Die Arten von SQL, mit denen dies möglich wäre, würden entweder eine kartesische Verknüpfung (potenziell höchst ineffizient) oder eine UNION disjunkter Spalten (ebenfalls hässlich) erfordern. Vermutlich hat die Unfähigkeit, dies in SQL auf eine saubere und effiziente Weise zu erreichen, das API-Design beeinflusst.

0 Stimmen

@ThomasW Dies sind die Sql-Abfragen, die das Programm generieren sollte: select * from master; select * from child1 where master_id = :master_id; select * from child2 where master_id = :master_id

2 Stimmen

Ein ähnlicher Fehler kann auftreten, wenn Sie mehr als eine List<child> con fetchType definiert für mehr als eine List<clield>

18voto

Prateek Singh Punkte 1089

Um dies zu beheben, nehmen Sie einfach Set anstelle von List für Ihr verschachteltes Objekt.

@OneToMany
Set<Your_object> objectList;

und vergessen Sie nicht, die fetch=FetchType.EAGER

wird es funktionieren.

Es gibt ein weiteres Konzept CollectionId in Hibernate, wenn Sie nur eine Liste verwenden möchten.

Aber denken Sie daran, dass Sie wird nicht die Unterlage zu beseitigen Kartesisches Produkt wie beschrieben von Vlad Mihalcea in seiner Antwort ¡!

2 Stimmen

Beide Empfehlungen, die Sie gemacht haben, sind sehr schlecht in Bezug auf die Leistung.

9voto

Christian Müller Punkte 872

Ich habe einen guten Blog-Beitrag über das Verhalten von Hibernate bei dieser Art von Objekt-Mappings gefunden: http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html

5 Stimmen

Willkommen bei Stack Overflow. Von reinen Link-Antworten wird jedoch generell abgeraten. Siehe die FAQ und insbesondere: stackoverflow.com/faq#Löschung .

7voto

Massimo Punkte 867

Können Sie EAGER-Listen in JPA aufbewahren und zu mindestens einer von ihnen die JPA-Annotation hinzufügen @OrderColumn (natürlich mit dem Namen eines zu bestellenden Feldes). Es sind keine spezifischen Hibernate-Anmerkungen erforderlich. Aber bedenken Sie, dass es leere Elemente in der Liste erzeugen könnte, wenn das gewählte Feld keine Werte ab 0 hat

 [...]
 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 @OrderColumn(name="orderIndex")
 private List<Child> children;
 [...]

in Children, dann sollten Sie das Feld orderIndex hinzufügen

3voto

Felipe Cadena Punkte 101

Wenn Sie zu komplexe Objekte mit saveral Sammlung könnte keine gute Idee, alle von ihnen mit EAGER fetchType haben, besser verwenden LAZY und wenn Sie wirklich brauchen, um die Sammlungen zu laden verwenden: Hibernate.initialize(parent.child) um die Daten abzurufen.

2voto

Mike Dudley Punkte 67

Wir haben versucht Satz anstelle von Liste und es ist ein Alptraum: Wenn Sie zwei neue Objekte hinzufügen, ist gleich () und hashCode () beide nicht unterscheiden! Weil sie keine ID haben.

Typische Tools wie Eclipse generieren diese Art von Code aus Datenbanktabellen:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
}

Sie können auch lesen dieser Artikel die genau erklärt, wie verkorkst JPA/Hibernate ist. Nach der Lektüre dieses, ich denke, dies ist das letzte Mal, dass ich jede ORM in meinem Leben verwenden.

Ich habe auch Domain Driven Design Leute getroffen, die grundsätzlich sagen, dass ORM eine schreckliche Sache sind.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X