JPA CriteriaBuilder - Как использовать оператор сравнения "IN"
Не могли бы вы мне помочь, как преобразовать следующие коды в оператор "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();
Внутренняя строка запроса преобразуется в приведенную ниже, поэтому я не получаю записи, созданные двумя пользователями, потому что она использует "И".
select generatedAlias0 from ScheduleRequest as generatedAlias0 where ( generatedAlias0.createdBy=:param0 ) and ( generatedAlias0.createdBy=:param1 ) order by generatedAlias0.trackingId asc
2 ответа
Если я хорошо понимаю, вы хотите присоединиться ScheduleRequest
с User
и применить in
пункт к userName
собственность субъекта User
,
Мне нужно немного поработать над этой схемой. Но вы можете попробовать этот трюк, который гораздо более читабелен, чем код, который вы опубликовали, и избегает 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
, Но сейчас я не могу это проверить, поэтому предпочитаю посмотреть, не хочет ли кто-нибудь еще попробовать.
Не идеальный ответ, хотя фрагменты кода могут помочь.
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);
}