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. Объединение двух предикатов ИЛИ
с использованием предиката И
Давайте рассмотрим вариант использования, когда нам нужно найти элементы, имеющие оба:
красный или синий цвет
И
А или Б класс
Мы можем легко сделать это, используя составные предикаты 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. Объединение двух предикатов И
с помощью предиката ИЛИ
С другой стороны, давайте рассмотрим случай, когда нам нужно найти элементы, имеющие либо:
красный цвет и класс D
OR
синий цвет и класс 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 .