web-dev-qa-db-ja.com

Hibernateは複数のバッグを同時に取り出すことはできません

HibernateはSessionFactoryの作成中にこの例外をスローします。

org.hibernate.loader.MultipleBagFetchException:同時に複数のバッグを取得することはできません

これが私のテストケースです。

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;

}

この問題はどうですか?私に何ができる?


_編集_

OK、私が抱えている問題は、別の "親"エンティティが私の親の中にあるということです。私の本当の振る舞いはこれです:

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はFetchType.EAGERを持つ2つのコレクションを好きではありませんが、これはバグのようです。私は珍しいことをしていません...

ParentまたはAnotherParentからFetchType.EAGERを削除すると問題は解決しますが、必要なので、実際の解決策はFetchTypeの代わりに@LazyCollection(LazyCollectionOption.FALSE)を使用することです( Bozho のおかげで)。

391
blow

私は新しいバージョンのhibernate(JPA 2.0をサポート)でこれを処理するべきだと思います。それ以外の場合は、コレクションフィールドに次のように注釈を付けることで回避できます。

@LazyCollection(LazyCollectionOption.FALSE)

@*ToManyアノテーションからfetchType属性を削除することを忘れないでください。

しかし、ほとんどの場合、Set<Child>List<Child>より適切であることに注意してください。したがって、本当にListが必要でない限り - Setに行きます

467
Bozho

List型からSet型に変更するだけです。

262
Ahmad Zyoud

Hibernate固有の@Fetchアノテーションをコードに追加します。

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

これにより、Hibernate bug HHH-1718 に関連する問題が修正されるはずです。

113
DaveRlz

この記事や他の記事で説明されているすべてのオプションを試してみた後、私は修正が続くことであるという結論に達しました。

すべてのXToManyの場所で@XXXToMany(mappedBy="parent", fetch=FetchType.EAGER)とその直後

@Fetch(value = FetchMode.SUBSELECT)

これは私のために働きました

23
Javier

修正するには、ネストしたオブジェクトのSetの代わりにListを使用します。

@OneToMany
Set<Your_object> objectList;

fetch=FetchType.EAGERを使うことを忘れないでください

それが動作します。

リストだけを使いたい場合は、Hibernateにもう1つの概念CollectionIdがあります。

18
Prateek Singh

私はこの種のオブジェクトマッピングにおけるHibernateの振る舞いについての良いブログ記事を見つけました: http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html

11

あなたはJPAでブースのEAGERリストを保持し、それらのうちの少なくとも1つにJPAアノテーション @OrderColumn を追加することができます(明らかに順序付けされるべきフィールドの名前)。特別な休止状態の注釈は必要ありません。ただし、選択したフィールドに0から始まる値がない場合は、リストに空の要素が作成される可能性があります。

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

子供たちでは、あなたはorderIndexフィールドを追加する必要があります

5
Massimo

この例外が発生する理由は、Hibernateがパフォーマンスに悪いデカルト積を実行することになるためです。

現在、Setの代わりにListを使用して問題を「修正」できますが、デカルト積は基礎となるSQLステートメントで引き続き機能するため、これを行うべきではありません。

熱心なフェッチは 重大なアプリケーションパフォーマンスの問題につながる可能性のあるひどいアイデア であるため、FetchType.EAGERからFetchype.LAZYに切り替えることをお勧めします。

複数レベルの階層全体で子エンティティを取得する必要がある場合は、最も内側の子から親まで選択する方が適切です この記事で説明されているように

3
Vlad Mihalcea

List の代わりに Set を試してみましたが、これは悪夢です。2つの新しいオブジェクトを追加すると、 equals ()および hashCode ()になります。両方を区別するのに失敗する!彼らはIDを持っていないからです。

eclipseのような典型的なツールはデータベーステーブルからその種のコードを生成します。

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

また、 この記事 を読んでも、JPA/Hibernateの混乱具合が正しく説明されています。これを読んだ後、私はこれが私が私の人生で何らかのORMを使う最後の時だと思います。

私は基本的にORMはひどいことだと言うDomain Driven Designの人たちとも出会いました。

1
Mike Dudley

Saveralコレクションを持つオブジェクトが複雑すぎる場合は、それらすべてにEAGER fetchTypeを使用するのはお勧めできません。LAZYを使用し、コレクションをロードする必要がある場合は、Hibernate.initialize(parent.child)を使用してデータを取得します。

1
Felipe Cadena

私にとっては、問題は _ eager _ フェッチをネストしていたことです。

1つの解決策は、入れ子になったフィールドを _ lazy _ に設定し、Hibernate.initialize()を使って入れ子になったフィールドを読み込むことです。

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