JPAおよび/または基準述語の組み合わせ

1. 概要

JPA基準APIを使用すると、データベースのレコードを照会するときに複数のAND / OR条件を簡単に追加できます。 このチュートリアルでは、複数のAND / OR述語を組み合わせたJPA基準クエリの簡単な例を調べます。
述語に慣れていない場合は、まずlink:/spring-data-criteria-queries[JPAの基本的な条件クエリ]について読むことをお勧めします。

2. サンプルアプリケーション

この例では、それぞれが_id、_ _name _、_ color_、および_grade_を持つ_Item_エンティティのインベントリを検討します。
@Entity
public class Item {

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

    // standard getters and setters
}

3. AND述語を使用した2つのOR述語の結合

両方を持つアイテムを見つける必要があるユースケースを考えてみましょう:
  1. 赤または青の色
    AND

  2. AまたはBグレード

    JPA Criteria APIの_and()_および_or()_複合述語を使用して、これを簡単に行うことができます*。
    まず、クエリを設定しましょう:
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<Item> criteriaQuery = criteriaBuilder.createQuery(Item.class);
Root<Item> itemRoot = criteriaQuery.from(Item.class);
次に、青色または赤色のアイテムを見つけるために_Predicate_を作成する必要があります。
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);
最後に、これら2つのAND _Predicate_を定義し、_where()_メソッドを適用して、クエリを実行します。
Predicate finalPredicate
  = criteriaBuilder.and(predicateForColor, predicateForGrade);
criteriaQuery.where(finalPredicate);
List<Item> items = entityManager.createQuery(criteriaQuery).getResultList();

4. OR述語を使用した2つのAND述語の結合

一方、次のいずれかを持つアイテムを見つける必要がある場合を考えてみましょう。
  1. 赤い色とグレードD
    OR

  2. 青色とグレードB

    ロジックは非常に似ていますが、ここでは最初に2つのAND __Predicate__sを作成し、次にOR _Predicate_を使用してそれらを結合します。
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を使用して、AND / OR述語を組み合わせる必要があるユースケースを実装しました。
いつものように、このチュートリアルで使用される完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/java-jpa[GitHub上]です。