it-swarm.com.de

Hibernate kann nicht mehrere Taschen gleichzeitig abholen

Hibernate löst diese Ausnahme während der SessionFactory-Erstellung aus:

org.hibernate.loader.MultipleBagFetchException: Es können nicht mehrere Taschen gleichzeitig abgerufen werden

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 mit diesem Problem? Was kann ich machen?


EDIT

OK, das Problem, das ich habe, ist, dass sich eine andere "übergeordnete" Entität in meinem übergeordneten Element befindet. Mein wirkliches Verhalten ist folgendes:

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;

}

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

Wenn Sie FetchType.EAGER aus Parent oder AnotherParent entfernen, wird das Problem gelöst, aber ich brauche es. Daher ist es eine echte Lösung, @LazyCollection(LazyCollectionOption.FALSE) anstelle von FetchType zu verwenden (danke Bozho für die Lösung).

378
blow

Ich denke, eine neuere Version von Hibernate (Unterstützung von JPA 2.0) sollte damit umgehen. Ansonsten können Sie dies umgehen, indem Sie die Sammlungsfelder mit folgenden Anmerkungen versehen:

@LazyCollection(LazyCollectionOption.FALSE)

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

Beachten Sie jedoch, dass ein Set<Child> in den meisten Fällen geeigneter ist als List<Child>. Wenn Sie also wirklich nicht List benötigen, gehen Sie zu Set.

454
Bozho

Wechseln Sie einfach von List-Typ zu Set-Typ.

252
Ahmad Zyoud

Alternativ können Sie Ihrem Code eine Hibernate-spezifische @Fetch-Anmerkung hinzufügen:

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

Dies sollte das Problem beheben, das mit dem Hibernate-Fehler zusammenhängt HHH-1718

100
DaveRlz

Nachdem ich mit jeder einzelnen Option, die in diesen Posts und anderen beschrieben wird, versucht habe, kam ich zu dem Schluss, dass es sich bei dem Update um Folgendes handelt.

In jeder XToMany Stelle @XXXToMany(mappedBy="parent", fetch=FetchType.EAGER) Und dazwischen nach

@Fetch(value = FetchMode.SUBSELECT)

Das hat bei mir funktioniert

22
Javier

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, fetch=FetchType.EAGER zu verwenden

es wird klappen.

Es gibt ein weiteres Konzept CollectionId in Hibernate, wenn Sie nur bei list bleiben möchten.

17
Prateek Singh

Ich habe in dieser Art von Objektzuordnungen einen guten Blogbeitrag über das Verhalten von Hibernate gefunden: http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneous.html

11

sie können Stand-EAGER-Listen in JPA führen und mindestens eine JPA-Annotation @OrderColumn hinzufügen (mit offensichtlich dem Namen eines zu bestellenden Feldes). Es sind keine speziellen Anmerkungen für den Ruhezustand erforderlich. Beachten Sie jedoch, dass in der Liste möglicherweise leere Elemente erstellt werden, wenn das ausgewählte Feld keine Werte enthält, die mit 0 beginnen

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

in Kinder sollten Sie dann das Feld orderIndex hinzufügen 

5
Massimo

Der Grund für diese Ausnahme ist, dass Hibernate am Ende ein kartesisches Produkt ausführt, das für die Leistung schlecht ist.

Obwohl Sie das Problem mithilfe von Set anstelle von List "beheben" können, sollten Sie dies nicht tun, da das kartesische Produkt immer noch in den zugrunde liegenden SQL-Anweisungen enthalten ist.

Sie sollten besser von FetchType.EAGER zu Fetchype.LAZY wechseln, da eifriges Abrufen eine schreckliche Idee ist, die zu kritischen Anwendungsleistungsproblemen führen kann .

Wenn Sie die untergeordneten Entitäten über eine mehrstufige Hierarchie abrufen müssen, wählen Sie besser das innerste untergeordnete Element bis zu den übergeordneten Elementen aus, wie in diesem Artikel erläutert .

3
Vlad Mihalcea

Wir haben Set anstelle von List ausprobiert, und es ist ein Albtraum: Wenn Sie zwei neue Objekte hinzufügen, können equals () und hashCode () nicht beide unterscheiden! Weil sie keine Id haben.

typische Tools wie Eclipse generieren diesen 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 diesen Artikel lesen, der richtig erklärt, wie durcheinander JPA/Hibernate ist. Nachdem ich das hier gelesen habe, denke ich, dass dies das letzte Mal ist, dass ich ORM in meinem Leben verwende.

Ich habe auch Domain Driven Design-Jungs getroffen, die sagen, dass ORM eine schreckliche Sache ist.

1
Mike Dudley

Wenn Sie über zu komplexe Objekte mit der Sammlung von Sammlungen verfügen, kann es nicht sinnvoll sein, alle Objekte mit EAGER fetchType zu verwenden. Verwenden Sie besser LAZY, und wenn Sie die Sammlungen wirklich laden müssen, verwenden Sie: Hibernate.initialize(parent.child), um die Daten abzurufen.

1
Felipe Cadena

Für mich bestand das Problem darin,EIFRIGEfetches verschachtelt zu haben.

Eine Lösung besteht darin, die verschachtelten Felder aufLAZYzu setzen und Hibernate.initialize () zu verwenden, um die verschachtelten Felder zu laden:

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