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 のおかげで)。
私は新しいバージョンのhibernate(JPA 2.0をサポート)でこれを処理するべきだと思います。それ以外の場合は、コレクションフィールドに次のように注釈を付けることで回避できます。
@LazyCollection(LazyCollectionOption.FALSE)
@*ToMany
アノテーションからfetchType
属性を削除することを忘れないでください。
しかし、ほとんどの場合、Set<Child>
はList<Child>
より適切であることに注意してください。したがって、本当にList
が必要でない限り - Set
に行きます
List
型からSet
型に変更するだけです。
Hibernate固有の@Fetchアノテーションをコードに追加します。
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<Child> childs;
これにより、Hibernate bug HHH-1718 に関連する問題が修正されるはずです。
この記事や他の記事で説明されているすべてのオプションを試してみた後、私は修正が続くことであるという結論に達しました。
すべてのXToManyの場所で@XXXToMany(mappedBy="parent", fetch=FetchType.EAGER)
とその直後
@Fetch(value = FetchMode.SUBSELECT)
これは私のために働きました
修正するには、ネストしたオブジェクトのSet
の代わりにList
を使用します。
@OneToMany
Set<Your_object> objectList;
fetch=FetchType.EAGER
を使うことを忘れないでください
それが動作します。
リストだけを使いたい場合は、Hibernateにもう1つの概念CollectionId
があります。
私はこの種のオブジェクトマッピングにおけるHibernateの振る舞いについての良いブログ記事を見つけました: http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html
あなたはJPAでブースのEAGERリストを保持し、それらのうちの少なくとも1つにJPAアノテーション @OrderColumn を追加することができます(明らかに順序付けされるべきフィールドの名前)。特別な休止状態の注釈は必要ありません。ただし、選択したフィールドに0から始まる値がない場合は、リストに空の要素が作成される可能性があります。
[...]
@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@OrderColumn(name="orderIndex")
private List<Child> children;
[...]
子供たちでは、あなたはorderIndexフィールドを追加する必要があります
この例外が発生する理由は、Hibernateがパフォーマンスに悪いデカルト積を実行することになるためです。
現在、Set
の代わりにList
を使用して問題を「修正」できますが、デカルト積は基礎となるSQLステートメントで引き続き機能するため、これを行うべきではありません。
熱心なフェッチは 重大なアプリケーションパフォーマンスの問題につながる可能性のあるひどいアイデア であるため、FetchType.EAGER
からFetchype.LAZY
に切り替えることをお勧めします。
複数レベルの階層全体で子エンティティを取得する必要がある場合は、最も内側の子から親まで選択する方が適切です この記事で説明されているように 。
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の人たちとも出会いました。
Saveralコレクションを持つオブジェクトが複雑すぎる場合は、それらすべてにEAGER fetchTypeを使用するのはお勧めできません。LAZYを使用し、コレクションをロードする必要がある場合は、Hibernate.initialize(parent.child)
を使用してデータを取得します。
私にとっては、問題は _ eager _ フェッチをネストしていたことです。
1つの解決策は、入れ子になったフィールドを _ lazy _ に設定し、Hibernate.initialize()を使って入れ子になったフィールドを読み込むことです。
x = session.get(ClassName.class, id);
Hibernate.initialize(x.getNestedField());