Frage

Hibernate wirft diese Ausnahme bei der Session Erstellung:

  

org.hibernate.loader.MultipleBagFetchException: können nicht gleichzeitig mehrere Beutel holen

Das ist mein Testfall:

Parent.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;

}

Child.java

@Entity
public Child {

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

 @ManyToOne
 private Parent parent;

}

Wie wäre es dieses Problem? Was kann ich tun?


Bearbeiten

OK, das Problem, das ich habe, ist, dass ein andere „Eltern“ Einheit in meinen Eltern, mein reales Verhalten ist dies:

Parent.java

@Entity
public Parent {

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

 @ManyToOne
 private AntoherParent anotherParent;

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

}

AnotherParent.java

@Entity
public AntoherParent {

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

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

}

Ruhezustand nicht wie zwei Sammlungen mit FetchType.EAGER, aber dies scheint ein Fehler zu sein, ich bin nicht ungewöhnlich, Dinge zu tun ...

Entfernen von FetchType.EAGER von Parent oder AnotherParent löst das Problem, aber ich brauche es, so wirkliche Lösung ist @LazyCollection(LazyCollectionOption.FALSE) zu verwenden, anstatt FetchType (dank Bozho für die Lösung).

War es hilfreich?

Lösung

Ich denke, eine neuere Version von Hibernate (mit Unterstützung für JPA 2.0) damit umgehen soll. Aber sonst kann man es umgehen, indem sie die Sammlung Felder mit Anmerkungen versehen mit:

@LazyCollection(LazyCollectionOption.FALSE)

Denken Sie daran, das fetchType Attribut aus der @*ToMany Anmerkung zu entfernen.

Aber beachten Sie, dass in den meisten Fällen eine Set<Child> ist besser geeignet als List<Child>, so dass, wenn Sie wirklich ein List brauchen - go für Set

Andere Tipps

Einfach von List Typ Set Typ verändern.

Fügen Sie eine Hibernate spezifische @Fetch Anmerkung zu Ihrem Code:

@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<Child> childs;

Dies sollte das Problem beheben, zu Hibernate Fehler im Zusammenhang HHH-1718

Nach dem mit jeder einzelnen Option versuchen, in diesen Beiträgen und andere beschreiben, kam ich zu dem Schluss, dass die das Update ist wie folgt.

In jedem XToMany Ort @XXXToMany(mappedBy="parent", fetch=FetchType.EAGER) und zwischen nach

@Fetch(value = FetchMode.SUBSELECT)

Das ist für mich gearbeitet

Um es zu beheben einfach Set anstelle von List für verschachteltes Objekt nehmen.

@OneToMany
Set<Your_object> objectList;

und vergessen Sie nicht fetch=FetchType.EAGER

zu verwenden,

es wird funktionieren.

Es gibt ein weiteres Konzept CollectionId in dem Ruhezustand, wenn Sie mit der Liste halten wollen.

fand ich eine gute Blog-Post über das Verhalten von Hibernate in dieser Art von Objekt-Zuordnungen: http : //blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html

Sie können Stand EAGER Listen in JPA halten und mindestens einer von ihnen die JPA-Annotation hinzufügen @OrderColumn (mit offensichtlich den Namen eines Feldes zu bestellen). Keine Notwendigkeit spezifischer Hibernate Annotations. Aber bedenken Sie könnte es leere Elemente in der Liste erstellen, wenn das gewählte Feld ab 0 keine Werte haben

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

bei Kindern dann sollten Sie das orderIndex Feld hinzufügen

Der Grund, warum Sie diese Ausnahme erhalten, dass Hibernate ein Kartesisches Produkt würde am Ende zu tun, die für die Leistung schlecht ist.

Nun, obwohl Sie könnten „fix“ das Problem durch Set statt List verwenden, sollten Sie das nicht tun, weil das Kartesisches Produkt wird nach wie vor in den zugrunde liegenden SQL-Anweisungen sehen sein.

Sie sind besser dran, da eifrig Abruf von FetchType.EAGER zu Fetchype.LAZY Schalt ist ein schreckliche Idee, die kritische Anwendung Performance-Probleme führen kann.

Wenn Sie die untergeordneten Entitäten über eine Multi-Level-Hierarchie zu holen, wählen Sie besser aus dem am weitesten innen Kind bis zu den Eltern, wie in diesem Artikel erläutert.

Wenn Sie zu komplexe Objekte mit saveral Sammlung nicht gute Idee sein könnte, alle mit EAGER fetchType, eine bessere Nutzung LAZY und haben, wenn Sie wirklich die Sammlungen verwenden laden müssen. Hibernate.initialize(parent.child) die Daten zu holen

Wir haben versucht, Set statt Liste , und es ist ein Alptraum: Wenn Sie zwei neue Objekte hinzufügen, gleich () und hashCode () fehlschlagen, beide zu unterscheiden! Denn sie haben keine ID.

typische Werkzeuge wie Eclipse erzeugen 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 ein href lesen <= "http://www.onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html?page= 1" rel = "nofollow noreferrer"> dieser Artikel , die richtig, wie verkorkst JPA / Hibernate erklärt wird. Nach der Lektüre dieses, ich denke, das ist das letzte Mal ich jede ORM in meinem Leben verwenden.

Ich habe auch Jungs Domain Driven Design Begegnung, die im Grunde sagt ORM ist eine schreckliche Sache.

Für mich ist das Problem verschachtelt wurde zu haben EAGER abruft.

Eine Lösung ist, die verschachtelten Felder auf LAZY und verwendet Hibernate.initialize (), um das verschachtelte Feld zu laden (s):

x = session.get(ClassName.class, id);
Hibernate.initialize(x.getNestedField());

Sie könnten eine neue Annotation verwenden diese zu lösen:

@XXXToXXX(targetEntity = XXXX.class, fetch = FetchType.LAZY)

In der Tat, holt den Standardwert ist FetchType.LAZY zu.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top