Перейти к основному содержимому

Объединение предикатов JPA и/или критериев

· 3 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

1. Обзор

API критериев JPA можно использовать для простого добавления нескольких условий И/ИЛИ при запросе записей в базе данных. В этом руководстве мы рассмотрим быстрый пример запросов критериев JPA, которые объединяют несколько предикатов AND/OR.

Если вы не знакомы с предикатами, мы предлагаем сначала прочитать об основных критериальных запросах JPA .

2. Образец заявления

В наших примерах мы рассмотрим перечень сущностей Item , каждая из которых имеет идентификатор, имя , цвет и класс :

@Entity
public class Item {

@Id
private Long id;
private String color;
private String grade;
private String name;

// standard getters and setters
}

3. Объединение двух предикатов ИЛИ с использованием предиката И

Давайте рассмотрим вариант использования, когда нам нужно найти элементы, имеющие оба:

  1. красный или синий цвет

    И

  2. А или Б класс

Мы можем легко сделать это, используя составные предикаты and() и or() API JPA Criteria .

Для начала настроим наш запрос:

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Item> criteriaQuery = criteriaBuilder.createQuery(Item.class);
Root<Item> itemRoot = criteriaQuery.from(Item.class);

Теперь нам нужно создать предикат для поиска элементов синего или красного цвета:

Predicate predicateForBlueColor
= criteriaBuilder.equal(itemRoot.get("color"), "blue");
Predicate predicateForRedColor
= criteriaBuilder.equal(itemRoot.get("color"), "red");
Predicate predicateForColor
= criteriaBuilder.or(predicateForBlueColor, predicateForRedColor);

Далее создадим Predicate для поиска предметов класса A или B:

Predicate predicateForGradeA
= criteriaBuilder.equal(itemRoot.get("grade"), "A");
Predicate predicateForGradeB
= criteriaBuilder.equal(itemRoot.get("grade"), "B");
Predicate predicateForGrade
= criteriaBuilder.or(predicateForGradeA, predicateForGradeB);

Наконец, мы определяем предикат AND для этих двух, применяем метод where() и выполняем наш запрос:

Predicate finalPredicate
= criteriaBuilder.and(predicateForColor, predicateForGrade);
criteriaQuery.where(finalPredicate);
List<Item> items = entityManager.createQuery(criteriaQuery).getResultList();

4. Объединение двух предикатов И с помощью предиката ИЛИ

С другой стороны, давайте рассмотрим случай, когда нам нужно найти элементы, имеющие либо:

  1. красный цвет и класс D

    OR

  2. синий цвет и класс B

Логика очень похожа, но здесь мы сначала создаем два предиката AND, а затем объединяем их с помощью предиката OR :

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Item> criteriaQuery = criteriaBuilder.createQuery(Item.class);
Root<Item> itemRoot = criteriaQuery.from(Item.class);

Predicate predicateForBlueColor
= criteriaBuilder.equal(itemRoot.get("color"), "red");
Predicate predicateForGradeA
= criteriaBuilder.equal(itemRoot.get("grade"), "D");
Predicate predicateForBlueColorAndGradeA
= criteriaBuilder.and(predicateForBlueColor, predicateForGradeA);

Predicate predicateForRedColor
= criteriaBuilder.equal(itemRoot.get("color"), "blue");
Predicate predicateForGradeB
= criteriaBuilder.equal(itemRoot.get("grade"), "B");
Predicate predicateForRedColorAndGradeB
= criteriaBuilder.and(predicateForRedColor, predicateForGradeB);

Predicate finalPredicate
= criteriaBuilder
.or(predicateForBlueColorAndGradeA, predicateForRedColorAndGradeB);
criteriaQuery.where(finalPredicate);
List<Item> items = entityManager.createQuery(criteriaQuery).getResultList();

5. Вывод

В этом руководстве мы использовали JPA Criteria API для реализации вариантов использования, в которых нам нужно было комбинировать предикаты И/ИЛИ.

Как обычно, полный исходный код, используемый для этого руководства, находится на GitHub .