1. 概要

JPA Criteria APIを使用すると、データベース内のレコードを照会するときに、複数のAND/OR条件を簡単に追加できます。 このチュートリアルでは、複数のAND/OR述語を組み合わせたJPA基準クエリの簡単な例を見ていきます。

述語に慣れていない場合は、最初に基本的なJPA基準クエリについて読むことをお勧めします。

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

この例では、 Item エンティティのインベントリを検討します。各エンティティには、 id、 name color 、およびがあります。 ] grade

@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 predicateForBlueColor
  = criteriaBuilder.equal(itemRoot.get("color"), "blue");
Predicate predicateForRedColor
  = criteriaBuilder.equal(itemRoot.get("color"), "red");
Predicate predicateForColor
  = criteriaBuilder.or(predicateForBlueColor, predicateForRedColor);

次に、述語を作成して、グレード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. 赤い色とグレードDOR
  2. 青い色とグレードB

ロジックは非常に似ていますが、ここでは最初に2つのAND Predicate を作成し、次に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述語を組み合わせる必要があるユースケースを実装しました。

いつものように、このチュートリアルで使用される完全なソースコードは、GitHub上のです。