2012-02-17 10 views
34

次のコードを基準ビルダーの "in"演算子に変換する方法を教えてください。 "in"を使ってユーザ名のリスト/配列を使ってフィルタリングする必要があります。JPA CriteriaBuilder - "IN"比較演算子の使用方法

また、JPA CriteriaBuilderを使用して検索しようとしましたが、「in」メソッドでは良好な結果が見つかりませんでした。 このトピックの参照URLを私に教えていただければ幸いです。ありがとう。

は、ここに私のコードです:

//usersList is a list of User that I need to put inside IN operator 

CriteriaBuilder builder = getJpaTemplate().getEntityManagerFactory().getCriteriaBuilder(); 
CriteriaQuery<ScheduleRequest> criteria = builder.createQuery(ScheduleRequest.class); 

Root<ScheduleRequest> scheduleRequest = criteria.from(ScheduleRequest.class); 
criteria = criteria.select(scheduleRequest); 

List<Predicate> params = new ArrayList<Predicate>(); 

List<ParameterExpression<String>> usersIdsParamList = new ArrayList<ParameterExpression<String>>(); 

for (int i = 0; i < usersList.size(); i++) { 
ParameterExpression<String> usersIdsParam = builder.parameter(String.class); 
params.add(builder.equal(scheduleRequest.get("createdBy"), usersIdsParam)); 
usersIdsParamList.add(usersIdsParam); 
} 

criteria = criteria.where(params.toArray(new Predicate[0])); 

TypedQuery<ScheduleRequest> query = getJpaTemplate().getEntityManagerFactory().createEntityManager().createQuery(criteria); 

for (int i = 0; i < usersList.size(); i++) { 
query.setParameter(usersIdsParamList.get(i), usersList.get(i).getUsername()); 
} 

List<ScheduleRequest> scheduleRequestList = query.getResultList(); 

内部クエリ文字列

は以下に変換され、それが使用して「AND」されているので、私は、二人のユーザーによって作成されたレコードを得ることはありません。

select generatedAlias0 from ScheduleRequest as generatedAlias0 where (generatedAlias0.createdBy=:param0) and (generatedAlias0.createdBy=:param1) order by generatedAlias0.trackingId asc 

答えて

69

私はよく理解していれば、あなたはUserScheduleRequestに参加して、エンティティUseruserNameプロパティにin句を適用したいです。

私はこのスキーマで少し作業する必要があります。しかし、あなたが投稿したコードよりもはるかに読みやすく、JoinのロジックをCriteria Queryの外で扱うので、Joinの部分を避けることができます。それが動作する場合

Expression<String> exp = scheduleRequest.get(ScheduleRequest_.createdBy); 

、あなたは可能性があります

List<String> myList = new ArrayList<String>(); 
for (User u : usersList) { 
    myList.add(u.getUsername()); 
} 
Expression<String> exp = scheduleRequest.get("createdBy"); 
Predicate predicate = exp.in(myList); 
criteria.where(predicate); 

あなたもこのライン置き換えることにより、メタモデルを使用することができ、よりタイプセーフなコードを記述するために:これで

Expression<String> exp = scheduleRequest.get("createdBy"); 

をロジックJoinCriteria Queryに追加してみてください。しかし、今はテストできないので、他の人が試してみたいかどうかを知りたいです。

+0

こんにちはperissf、あなたの返信のおかげで。私は、 "ScheduleRequest_"は何ですか、お願いできますか?どのように私はそれを作成するのですか? – Jemru

+2

JPAプロバイダによって自動生成されたMetamodelクラスです。 Hibernateを使用している場合は、このリンクを参照してください。http://docs.jboss.org/hibernate/jpamodelgen/1.0/reference/en-US/html_single/ – perissf

+0

疑似コードを読むと、タイプの不一致が考えられます。 userNames(String)またはuserIds(Integer/Long)に参加していますか? Pls私に私の答えを更新できるように私に教えてください – perissf

13

完全な回答ではありませんが、コードスニペットが役立つ場合があります。

public <T> List<T> findListWhereInCondition(Class<T> clazz, 
      String conditionColumnName, Serializable... conditionColumnValues) { 
     QueryBuilder<T> queryBuilder = new QueryBuilder<T>(clazz); 
     addWhereInClause(queryBuilder, conditionColumnName, 
       conditionColumnValues); 
     queryBuilder.select(); 
     return queryBuilder.getResultList(); 

    } 


private <T> void addWhereInClause(QueryBuilder<T> queryBuilder, 
      String conditionColumnName, Serializable... conditionColumnValues) { 

     Path<Object> path = queryBuilder.root.get(conditionColumnName); 
     In<Object> in = queryBuilder.criteriaBuilder.in(path); 
     for (Serializable conditionColumnValue : conditionColumnValues) { 
      in.value(conditionColumnValue); 
     } 
     queryBuilder.criteriaQuery.where(in); 

    } 
+1

ありがとう@gbagga、このことは私を助けてくれました!上記のメソッド(exp.in(myList))は、 "CriteriaBuilder"を使用しているときは機能しません。 メソッドは、criteriaBuilderを使用するときに "IN"句に使用するメソッドです。名誉! – roneo