2012-02-17 165 views
34

您可以請幫助我如何將以下代碼轉換爲使用條件構建器的「in」運算符? 我需要使用「in」使用用戶名列表/數組進行過濾。JPA CriteriaBuilder - 如何使用「IN」比較運算符

我也嘗試使用JPA CriteriaBuilder - 「in」方法進行搜索,但無法找到好結果。 所以,如果你能給我這個主題的參考網址,我將非常感激。謝謝。

這裏是我的代碼:

//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

如果我沒有理解好了,你想加入ScheduleRequestUserin條款適用於實體UseruserName財產。

我需要在這個模式上工作一下。但是,您可以嘗試使用這個技巧,它比您發佈的代碼更具可讀性,並避免使用Join部分(因爲它處理標準查詢外部的Join邏輯)。

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"); 

與此:

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

如果成功,那麼你可能嘗試將Join邏輯添加到Criteria Query。但現在我無法測試它,所以我更願意看看其他人是否想嘗試。

+0

嗨perissf,謝謝你的回覆。請問,請問什麼是「ScheduleRequest_」?我如何創建它? – Jemru 2012-02-17 09:49:39

+2

它是您的JPA提供程序自動生成的元模型類。如果您使用Hibernate,請查看此鏈接http://docs.jboss.org/hibernate/jpamodelgen/1.0/reference/en-US/html_single/ – perissf 2012-02-17 09:52:15

+0

閱讀我的僞代碼,我發現可能的類型差異。你是否加入了userNames(String)或userIds(Integer/Long)?請讓我知道,以便我可以更新我的答案 – perissf 2012-02-17 09:55:39

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 2015-09-04 15:47:00