2011-08-09 6 views
8

私は1つのSQL文で実行したいHibernateの基準呼び出しを持っています。私がしようとしているのは、外部結合を使用して子をロードする際に、値の範囲(SQL IN句)のプロパティを持つ子を持つ親のインスタンスを選択することです。ここで私がこれまで持っているものです。子に制限があるHibernateの基準

Criteria c = session.createCriteria(Parent.class); 

c.createAlias("children", "c", CriteriaSpecification.LEFT_JOIN) 
      .setFetchMode("c", FetchMode.JOIN) 
      .add(Restrictions.in("c.property", properties)); 

c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

return c.list(); 

ここではいくつかのサンプルデータです:私が何をしたいか

Parent 
Parent ID 
A 
B 
C 

Children 
Child ID Parent ID property 
...   A   0 
...   A   2 
...   A   7 
...   B   1 
...   C   1 
...   C   2 
...   C   3 

は、子の1つは、私と同じ性質を持っている場合、親とそのすべての子供たちを返していますバインドパラメータ。プロパティが{2}を含む配列であるとしましょう。この場合、コールは親AとCを返しますが、子コレクションは要素2のみを含みます。親[子供]:私が欲しいもの

A [2] & C [2]

は次のとおりです。

A [0、2、7] & C [1、2 3]

これはバグではない場合、壊れた意味論のようです。 A.getChildren()やC.getChildren()を呼び出して1レコードを返す方法が正しいとは思われませんでした。これは投影ではありません。私。私はデフォルトのフェッチを選択使用するクエリを増大させる場合、それはalbietクエリの多くで、適切な子供のコレクションを返します。

c.createAlias("children", "c").add(
     Restrictions.in("c.property", properties)); 

これはバグですか?そうでない場合は、どうすれば希望の結果を達成できますか?

答えて

1

getChildren()はgetter/setterの名前に過ぎません。クエリによってオブジェクトの取り込み方法が決まります。

私は、最初の部分は、あなたが望む何を得ることはありません

SELECT * FROM Parent 
INNER JOIN Child c ON ... 
WHERE c.property in (x,y,z) 

を出してくれることを、ここで推測するつもりです。 What'dあなたは生のSQLでこれを書いていた場合の対処したいと思い、このです:最後のものは、このクエリを作成していない場合、適切にあなたの基準を再配置

SELECT * FROM Parent 
WHERE ParentID IN (SELECT DISTINCT parentID FROM Child WHERE c.property in (x,y,z)) 

は、トリックを行う可能性があります。 (それぞれにハイバーネーションが生成されていることを投稿することもできますか?)

+1

いいえ、SQLは簡単な部分です。私が探しているのは基準の呼び出しです。 ;)また、子エンティティにデータを取り込むために外部結合が必要になることに注意してください。 –

+0

2番目のクエリは親を取得し、遅延読み込みは子ですか? – dfb

+0

はい、返される各親レコードに対して、私が避けようとしている子クエリが実行されています。これは実際には欠陥であるかもしれませんが、誰かが回避策を持っているかどうか不思議です:https://hibernate.onjira.com/browse/HHH-3524 –

0

私は子クラスで基準を開始します。あなたはすべての子を持つリストを取得し、各子供のために反復して親を得ることができます。

2
 Criteria c = session.createCriteria(Parent.class); 

    c.createAlias("children", "children"); 
    c.add(Restrictions.in("children.property", properties)); 

    c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

    return c.list(); 
0

これは、回避方法で行うことができます。

Criteria c1 = session.createCriteria(Child.class); 
c1.add(Restrictions.in("property", properties)); 
c1.setProjection(Projections.distinct(Projections.property("parentId"))); 
List<Integer> parentIds = c1.list(); 

Criteria c2 = session.createCriteria(Parent.class); 
c2.createAlias("children", "children"); 
c2.add(Restrictions.in("id", parentIds)); 
return c2.list(); 
関連する問題