2011-07-18 3 views
7

JAP基準のクエリをブール値の出力にする方法がわかりません。「存在する」JPA Criteria Query句がtrueまたはfalseを返したかどうかを正しく判別する方法は?

select 1 from dual where exists (...); 

私はサブクエリで行ったwhere exists (...)部分は、私は外部クエリに苦しんだ:

目標は、オラクルに描画されたときに、このようになります基準のクエリを持つことです。

exists句のサブクエリがtrueまたはfalseを返したかどうかを判断することです。

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); 

CriteriaQuery<Object> query = criteriaBuilder.createQuery(); 
query.from(Boolean.class); 
query.select(criteriaBuilder.literal(true)); 

Subquery<Location> subquery = query.subquery(Location.class); 
Root<Location> subRootEntity = subquery.from(Location.class); 
subquery.select(subRootEntity); 

Path<?> attributePath = subRootEntity.get("State"); 
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX")); 
subquery.where(predicate); 
query.where(criteriaBuilder.exists(subquery)); 

TypedQuery<Object> typedQuery = em.createQuery(query); 

しかし、最後の行は、ブールが実体ではないと言って失敗します。

これは私が得たものです。私の問題は、結果が1または0、真または偽、およびエンティティではないので、クエリの「from」部分を表現する方法がわかりません。

私は任意のエンティティを取得し、結果のリストはサイズ1を持っているかどうかを確認することも可能だろうが、私はストレートの両方それらの列を取り出すの不必要な作業を回避し、また、学ぶために、ブール結果を取得する方法を学ぶためにしようとしていますどうやってするの。

これはまったく可能ですか?

ありがとうございました! Eduardo

+2

をいいえ、あなたが直接それを行うことはできませんが、一般的な方法は、カウントがゼロ偽他の真よりも大きい場合、結果セットのすなわちの数をチェックすることです。 – Shahzeb

答えて

6

あなたは一つの特性(例えばID)のための選択を行うと、あなたはDBは、(すべてのインスタンスを数えるなど)必要以上に仕事をしていないことを確認するように最大の結果が1に戻って設定することができます。結果リストは空(存在=偽)か要素が1つ(存在=真)のいずれかになります。

+0

これは私が探していたものです。DBMSを必要以上に機能させることなく、これを達成する方法です。ありがとう!! –

0

私は問題がquery.from(Boolean.class)であると思います。 "ブール値から選択オブジェクト"クエリを作成しようとします。あなたは戻り値の型としてブールをしたい場合は、(おそらく、サブクエリのテーブルから)有効なクエリを作成するには、既存のエンティティテーブルからクエリその後

CriteriaQuery<Boolean> query = criteriaBuilder.createQuery(Boolean.class) 

を使用する必要があります。デュアルテーブルをマップするのを除いて、デュアルワークから作成するとは思いません。

-2

すべてのロジックがJPAになければならない理由はありますか?そうでない場合は、SELECT COUNTを使用してブール値を設定する条件を使用しないでください。

Boolean exists = false; 
int count = selectCountQuery(); 
if (count > 0) { 
    exists = true; 
} 
10

はい、可能です。 dualテーブルに対応するエンティティがあると仮定すると、CriteriaQuery#fromにそのエンティティクラスを使用することになります。

CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); 

CriteriaQuery<Boolean> query = criteriaBuilder.createQuery(Boolean.class); 
query.from(dual.class); 
query.select(criteriaBuilder.literal(true)); 

Subquery<Location> subquery = query.subquery(Location.class); 
Root<Location> subRootEntity = subquery.from(Location.class); 
subquery.select(subRootEntity); 

Path<?> attributePath = subRootEntity.get("State"); 
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX")); 
subquery.where(predicate); 
query.where(criteriaBuilder.exists(subquery)); 

TypedQuery<Boolean> typedQuery = em.createQuery(query); 
2

私はこれは古い質問ですけど、誰が見ているために:どのようにブール値を返すメソッドでSpringのJPAの@query注釈と(あなたのDBの実装に依存する)を選択した場合のクエリを使用しようとしてについて。例(MySQLの)の場合:名前のJPAまたはクエリビルダメソッドは非常にあなたがそれらをしたい何をしていないとき

@Query("SELECT CASE WHEN COUNT(l) > 0 THEN TRUE ELSE FALSE END FROM Location l WHERE l.state=?1") 
boolean locationForStateExists(String state); 

時にはちょうど@queryでクエリ文字列を使用すると、命の恩人することができます。

+0

これは基本的な問題である 'count()'に依存しています。 Hibernateは 'where'節を除いて' exists'キーワードをサポートしていません。これはOPが尋ねていることを達成しません。 'count'を選択すると潜在的に非常に遅くなる可能性があります(' where'句の存在、インデックスの存在などに依存します)。一方、 'exists'節は最初のオカレンスで高速に失敗します。本当に残念ですが、JPA/Hibernateはこの些細な最適化をサポートしていません。 –

1

休止5が働いている:

Subquery<Integer> subquery = query.subquery(Integer.class); 
Root<Location> subRootEntity = subquery.from(Location.class); 
subquery.select(criteriaBuilder.literal(1)); 

Path<?> attributePath = subRootEntity.get("State"); 
Predicate predicate = criteriaBuilder.equal(attributePath, criteriaBuilder.literal("TX")); 
subquery.where(predicate); 
query.where(criteriaBuilder.exists(subquery)); 
+0

ありがとうございました! –