2016-05-03 21 views
0

JPAとCriteria APIを使用してメタモデルを使用しない動的クエリを作成しようとしています。テーブルとLEFT JOIN AND条件式APIを使用したAND演算子

Foo: 
ID 
1 
2 
3 
4 

Bar: 
ID FooID Number 
1 2  44 
2 2  55 
3 3  55 

私は一致するバーが数44(Fooの1、3、4を期待)

持っていないすべてのFooエンティティを取得したいですSQLは次のようになります。

select distinct * 
from Foo foo0_ 
left join Bar bar0_ on foo0_.ID=bar0_.FooID and bar0_.Number=44 
where bar0__.id is null; 

私のコードは次のようになります。

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Foo> cq = cb.createQuery(Foo.class); 
Root<Foo> fooRoot = cq.from(Foo.class); 
cq.select(fooRoot).distinct(true); 

List<Predicate> allPredicates = new ArrayList<Predicate>(); 
List<Predicate> orPredicates = new ArrayList<Predicate>(); 
List<Predicate> andPredicates = new ArrayList<Predicate>(); 
andPredicates.add(cb.equal(fooRoot.join("bars", JoinType.LEFT).get("number"), 44)); 
andPredicates.add(cb.isNull(fooRoot.join("bars", JoinType.LEFT).get("ID"))); 
orPredicates.add(cb.and(andPredicates.toArray(new Predicate[andPredicates.size()]))); 
allPredicates.add(cb.or(orPredicates.toArray(newPredicate[orPredicates.size()]))); 

cq.where(allPredicates.toArray(new Predicate[allPredicates.size()])); 
TypedQuery<Foo> query = em.createQuery(cq); 
query.getResultList(); 

をしかし、それは、このSQLを生成します:

select distinct * 
from Foo foo0_ 
left outer join Bar bar1_ on foo0_.id=bar1_.FooID 
left outer join Bar bar2_ on foo0_.id=bar2_.FooID 
where bar1_.Number=44 and (bar2_.id is null); 

をして何のFooを返しません。

アイデア?ありがとうございました!

答えて

1

これはJPAの実装が指定されておらず、明らかにSQLがそれぞれ異なる場合があります。

あなたの参加は間違っています。各joinコールはJOINを行い、あなたが書いたものが正しい場合にのみ1回の結合が必要です。また、JPA 2.1の "ON"条件を(WHEREに入れるのではなく)結合に利用することもできます。

CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Foo> cq = cb.createQuery(Foo.class); 
Root<Foo> fooRoot = cq.from(Foo.class); 
cq.select(fooRoot).distinct(true); 

Join barJoin = fooRoot.join("bars", JoinType.LEFT); 
Predicate onCond = cb.equal(barJoin.get("number"), 44); 
barJoin.on(onCond); 

次に、barJoinを使用する以外は同じ質問をしてください。これらのAND条件が何をしようとしているのかはわかりません。あなたの提案するSQLにはそのようなものはありません。

+0

私はHibernate JPA 2.0を使用していますので残念ながらbarJoin.on(onCond)は動作しません。 _and_、_or_および_all_述部は、異なる表および異なるパラメーターで動的照会を構築するためのものです。 – Solver42

+0

JPA 2.1に変更してコードを使用しましたが、qbをcbに変更し、AbstractMethodErrorを取得しました:org.hibernate.ejb.criteria.path.ListAttributeJoin.on(Ljavax/persistence/criteria/Expression;)Ljavax/persistence/criteria/join; qbはQueryBuilderであり、必要ですか? JPA依存関係でそれを見つけることができません。 – Solver42

+0

はい、JPA 2.1の "ON"条件を満たしました。私は正しい方法で実行したいのでJPA 2.1に変更しましたが、動作させることができません。 qbとは何ですか? – Solver42

関連する問題