JPA CriteriaBuilder – 如何使用“IN”比较运算符

你能帮我如何将下面的代码转换为使用标准构build器的“in”运算符? 我需要通过使用“in”使用列表/数组的用户名进行过滤。

我也尝试使用JPA CriteriaBuilder进行search – “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(); 

内部的查询string被转换为下面,所以我没有得到这两个用户创build的logging,因为它使用“AND”。

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

如果我理解的很好,你想和User一起joinScheduleRequest ,并将in子句应用到实体UseruserName属性上。

我需要在这个模式上工作一下。 但是你可以尝试一下这个技巧,它比你发布的代码更可读,并且避免了Join部分(因为它处理Criteria Query之外的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); 

为了编写更多types安全的代码,您也可以使用Metamodelreplace此行:

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

有了这个:

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

如果它工作,那么你可以尝试添加Join逻辑到Criteria Query 。 但现在我无法testing,所以我更喜欢看别人是否想尝试。

虽然可能是代码片段可能会有帮助,但这并不是一个完美的答案。

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