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

Criteria API — пример IN-выражений

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

1. Обзор

Мы часто сталкиваемся с проблемами, когда нам нужно запрашивать сущности на основе того, является ли однозначный атрибут членом данной коллекции.

В этом уроке мы узнаем, как решить эту проблему с помощью Criteria API .

2. Примеры объектов

Прежде чем мы начнем, давайте взглянем на сущности, которые мы собираемся использовать в нашем описании.

У нас есть класс DeptEmployee , который имеет отношение « многие к одному » с классом отдела :

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

private String title;

@ManyToOne
private Department 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. Выражение.In

В качестве альтернативы мы можем использовать набор перегруженных методов in() из интерфейса Expression :

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

В отличие от CriteriaBuilder. in() , Expression.in() принимает набор значений. Как мы видим, это также немного упрощает наш код.

5. Выражения IN с использованием подзапросов

До сих пор мы использовали коллекции с предопределенными значениями. Теперь давайте рассмотрим пример, когда коллекция создается на основе вывода подзапроса.

Например, мы можем получить все 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() в качестве выражения для поиска сущности отдела .

6. Заключение

В этой быстрой статье мы узнали о различных способах выполнения операции IN с помощью Criteria API. Мы также изучили, как использовать Criteria API с подзапросами.

Наконец, полная реализация этого руководства доступна на GitHub .