web-dev-qa-db-ja.com

Hibernateで複数の子をフェッチするために左結合する方法は?

私はhibernateを使用していますが、オブジェクトのすべての子をフェッチするhqlクエリの作成に問題があります。

例:オブジェクトユーザーには、車のリストと友達のリストがあります。

彼の車でユーザーを取得するには、次のクエリを使用します。

from User u left join fetch u.cars where u.id = ?

これは問題なく機能するので、次のクエリを使用して、ユーザーを車や友達と簡単に見つけることができると思いました。

from User u left join fetch u.cars left join fetch u.friends where u.id = ?

しかし、これは私に次のエラーを与えます:

HibernateException:複数のバッグを同時にフェッチできない

今私の質問は:休止状態で複数の子供をフェッチする正しい方法は何ですか?

19
Bjorn Rombaut

子コレクションの多くて1つはバッグでなければなりません(つまり、リストとして宣言されています)。他のコレクションをセットとして宣言すると、機能します。

ただし、このようなフェッチ結合を実行すると、行のデカルト積が生成されることに注意してください。両方のコレクションに100の要素がある場合、そのようなクエリはデータベースから10,000行を取得します。 1つのコレクションをフェッチする最初のクエリと、もう1つのコレクションをフェッチする2番目のクエリを実行する方が効率的な場合があります(これにより、取得される行数が200に減少します)。これは、あなたが抱えている問題を回避する方法でもあります。

select u from User u left join fetch u.cars where u.id = :id;
select u from User u left join fetch u.friends where u.id = :id;
12
JB Nizet

コレクション/リスト(バッグ)の問題が発生しました。

これに関するHibernate公式「問題」へのリンクは次のとおりです: https://hibernate.atlassian.net/browse/HHH-1718 。ご覧のとおり、2006年にオープンし、現在もオープンしています。

JB Nizetが提案することに加えて、モデルでコレクションまたはリストの代わりにセットを使用することをお勧めします(可能な場合)。それ以外の場合は、コレクション/リストをFetchMode.SUBSELECTおよび最後のオプション(実装が面倒)として指定することもできます。 )、@ OneToMany/@ ManyToManyで@IndexColumnを使用できます。

このブログ記事では、ソリューションの実装について説明します。 http://jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

つまり、回避策を除いて、やりたいことを正確に行うための解決策はありません。

お役に立てれば!

編集:タイプミス

8
1lln3ss

アプリケーション/データベースには重すぎるため、2つの個別の基準を作成してデータを個別に取得する必要があるため、不可能です。

Cat cat = sess.createCriteria(Cat.class)
              .add(Restrictions.like("name", "F%"))
              .uniqueResult();

List kitten = sess.createCriteria(Kitten.class)
                  .add(Restrictions.eq("cat", cat))
                  .createCriteria("kittens")
                  .add(Restrictions.like("name", "F%"))
                  .list();

List mate = sess.createCriteria(Mate.class)
                .add(Restrictions.eq("cat", cat))
                .createCriteria("mate")
                .add(Restrictions.like("name", "F%"))
                .list();
0
aish