以下を含むエンティティがあります。
_@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "assessment")
@OrderBy(value = "order ASC")
private List<AssessmentPart> assessmentParts = new LinkedList<>();
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "assessment")
private List<AssessmentText> texts = new LinkedList<>();
_
ご覧のように、2つのコレクションを積極的にロードする必要があります。これは機能せず、Hibernateは例外をスローします。
_Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
_
これは、Hibernateが一度に複数のコレクションを取得できないためです。ただし、List
をSet
に変更し、LinkedList
をHashSet
に変更すると、この部分は正常に機能しますが、他の部分-より厄介な問題が発生します。
次を使用してデータベースからエンティティを取得しようとしているとき:
_entityManager.find(entityClass, primaryKey);
_
それは失敗します:
_org.hibernate.AssertionFailure: null identifier
_
find
メソッドに渡すIDがnullではないことを確認しました。デバッグしましたが、これは確かです。 Hibernate内で何らかの形で消えます。
コレクションタイプをLAZY
に変更すると、すべてがエラーなしで機能しますが、EAGER
を使用する必要がある状況があります。
誰かがそれを修正する方法を持っていますか?セットはあるがアサーションエラーの発生を防ぐか、リストはあるが複数のフェッチバッグエラーを避けることができます。
使っています:
_Hibernate 4.2.2.Final
Tomcat 7
JPA 2.0
JDK 1.7
_
[〜#〜] edit [〜#〜]
@Fetch(FetchMode.SELECT)
を追加すると問題が修正され、EAGER
タイプで複数のリストを使用できることを発見しましたが、Hibernate固有の注釈を使用しないことでこれを解決できますか?そして、そもそも問題を解決したのはなぜですか?
この問題の根本的な原因は、HibernateがSQLクエリ結果をフェッチするときに、どの子要素がどのコレクションに属しているかを知る簡単な方法がないことです。例付きの詳細な説明については、 このブログエントリ を参照してください。要約すると、次の回避策があります。
@Fetch(FetchMode.SELECT)
を使用して各コレクションを個別にロードします@IndexColumn(name="LIST_INDEX")
を追加して、バッグではなくリストの使用を強制しますHibernateを使用していて、Hibernateアノテーションの使用を気にしない場合:
コレクションフィールドに以下の注釈を付けます。
@LazyCollection(LazyCollectionOption.FALSE)
@OneToManyアノテーションからfetchType属性を忘れずに削除してください。