1. 概要

単一値の属性が特定のコレクションのメンバーであるかどうかに基づいてエンティティをクエリする必要があるという問題に遭遇することがよくあります。

このチュートリアルでは、 CriteriaAPIを使用してこの問題を解決する方法を学習します。

2. サンプルエンティティ

始める前に、記事で使用するエンティティを見てみましょう。

多対1の関係Departmentクラスを持つDeptEmployeeクラスがあります。

@Entity
public class DeptEmployee {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    private String title;

    @ManyToOne
    private Department department;
}

また、複数の DeptEmployeesにマップするDepartmentエンティティ:

@Entity
public class Department {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private long id;

    private String name;

    @OneToMany(mappedBy="department")
    private List<DeptEmployee> employees;
}

3. CriteriaBuilder.In

まず、CriteriaBuilderインターフェースを使用しましょう。 in()メソッドは式を受け入れ、CriteriaBuilder.Inタイプの新しい述語を返します。指定された式が値のリストに含まれているかどうかをテストするために使用できます。

CriteriaQuery<DeptEmployee> criteriaQuery = 
  criteriaBuilder.createQuery(DeptEmployee.class);
Root<DeptEmployee> root = criteriaQuery.from(DeptEmployee.class);
In<String> inClause = criteriaBuilder.in(root.get("title"));
for (String title : titles) {
    inClause.value(title);
}
criteriaQuery.select(root).where(inClause);

4. Expression.In

または、 Expressionインターフェイスからオーバーロードされたin()メソッドのセットを使用することもできます。

criteriaQuery.select(root)
  .where(root.get("title")
  .in(titles));

CriteriaBuilder.in()とは対照的に、Expression.in()は値のコレクションを受け入れます。ご覧のとおり、コードも少し単純化されています。

5. サブクエリを使用したIN

これまで、事前定義された値を持つコレクションを使用してきました。 次に、コレクションがサブクエリの出力から派生する場合の例を見てみましょう。

たとえば、 Department、に属するすべての DeptEmployee を、名前に指定されたキーワードを使用してフェッチできます。

Subquery<Department> subquery = criteriaQuery.subquery(Department.class);
Root<Department> dept = subquery.from(Department.class);
subquery.select(dept)
  .distinct(true)
  .where(criteriaBuilder.like(dept.get("name"), "%" + searchKey + "%"));

criteriaQuery.select(emp)
  .where(criteriaBuilder.in(emp.get("department")).value(subquery));

ここでは、サブクエリを作成し、それを式として value()に渡して、Departmentエンティティを検索しました。

6. 結論

このクイック記事では、CriteriaAPIを使用してIN操作を実現するさまざまな方法を学びました。 また、サブクエリでCriteriaAPIを使用する方法についても説明しました。

最後に、このチュートリアルの完全な実装は、GitHub利用可能です。