Подтвердить что ты не робот

JPA CriteriaBuilder - Как использовать оператор сравнения "IN"

Не могли бы вы помочь мне преобразовать следующие коды в использование оператора "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();

Внутренняя строка запроса преобразуется ниже, поэтому я не получаю записи, созданные двумя пользователями, потому что использует "AND".

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

Ответ 1

Если я хорошо понимаю, вы хотите присоединиться 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);

Чтобы написать более безопасный код, вы также можете использовать Metamodel, заменив эту строку:

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

с этим:

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

Если это работает, вы можете попытаться добавить логику Join в Criteria Query. Но сейчас я не могу его протестировать, поэтому я предпочитаю видеть, хочет ли кто-нибудь другой попробовать.

Ответ 2

Не идеальный ответ, хотя могут быть фрагменты кода, которые могут помочь.

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

    }