Spring boot Можно ли сгруппировать предикаты или использовать 'in' условно?

У меня проблемы с правильной группировкой запроса с помощью CriteriaBuilder а также Predicates,

Я хочу создать запрос, который может генерировать что-то вроде:

SELECT * from tableName where columnA = '1234' and (columnB Like '%33%' or columnB Like '%44%')

Но что я получаю (очевидно, ожидая, глядя на код):

SELECT * from tableName where columnA = '1234' and columnB Like '%33%' or columnB Like '%44%'

Который не дает тот же результат, что и первый запрос.

Я пытался обойти это, но я впервые работаю с критериями Builder и предикатами. Вот код:

CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Foo> criteriaQuery = builder.createQuery(Foo.class);
Root r = criteriaQuery.from(Foo.class);
Predicate predicate = builder.conjunction();
for(Map.Entry<String, String> entry : searchParams.entrySet()){
    if((entry.getKey().equalsIgnoreCase("columnK") || entry.getKey().equalsIgnoreCase("columnY") ||
            entry.getKey().equalsIgnoreCase("columnZ") || entry.getKey().equalsIgnoreCase("columnJ")) && !Strings.isNullOrEmpty(entry.getValue())){
                        predicate = builder.and(predicate,
                    builder.like(r.get(entry.getKey()),
                            String.format("%%%s%%", entry.getValue().toString())));
    }
    else if(entry.getKey().equalsIgnoreCase("theDate") && !Strings.isNullOrEmpty(entry.getValue())){
        predicate = builder.and(predicate, builder.equal(r.get(entry.getKey()), entry.getValue()));
    }
}

//here's where the problem is ... I realize I can use IN, but I also didn't get that to work
boolean isFirstDone = false;
for(String oneId: idStringList){
    if(!isFirstDone) {
        predicate = builder.and(predicate, builder.equal(r.get("acceptorId"), oneId));
        isFirstDone = true;
    }
    else{
        predicate = builder.or(predicate, builder.equal(r.get("acceptorId"), oneId));
    }
}
criteriaQuery.where(predicate);

Спасибо.

1 ответ

Решение

Итак, я просто взломал это после тщательного прочтения этого ответа /questions/29720585/jpa-criteriabuilder-kak-ispolzovat-operator-sravneniya-in/29720599#29720599 Решение не совсем то, что мне нужно, но оно помогло... много

Я создал путь и соединил его с моим предикатом.

Вот что изменилось:

Это:

boolean isFirstDone = false;
for(String oneId: idStringList){
    if(!isFirstDone) {
        predicate = builder.and(predicate, builder.equal(r.get("acceptorId"), oneId));
        isFirstDone = true;
    }
    else{
        predicate = builder.or(predicate, builder.equal(r.get("acceptorId"), oneId));
    }
}

стали:

Path<Object> path = r.get("acceptorId");
CriteriaBuilder.In<Object> in = builder.in(path);
for (String oneId: idStringList) {
    in.value(oneId);
}
predicate = builder.and(predicate, in);

Довольно просто, несмотря на все проблемы, которые мне потребовалось решить.

Надеюсь, это поможет кому-то еще!

Другие вопросы по тегам