1. Обзор
Мы часто сталкиваемся с проблемами, когда нам нужно запрашивать сущности на основе того, является ли однозначный атрибут членом данной коллекции.
В этом руководстве мы узнаем, как решить эту проблему с помощью API критериев .
2. Примеры объектов
Прежде чем мы начнем, давайте взглянем на сущности, которые мы собираемся использовать в нашей статье.
У нас есть класс DeptEmployee, который имеет отношение «многие к одному» с классом Department :
@Entity public class DeptEmployee { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String title; @ManyToOne private Department department; }
Кроме того, объект Department, который сопоставляется с несколькими сотрудниками DeptEmployees :
@Entity public class Department { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String name; @OneToMany(mappedBy="department") private List employees; }
3. CriteriaBuilder.In
Прежде всего, воспользуемся интерфейсом CriteriaBuilder . В () метод принимает выражение и возвращает новый Predicate из CriteriaBuilder.In типа . Его можно использовать для проверки, содержится ли данное выражение в списке значений:
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(DeptEmployee.class); Root root = criteriaQuery.from(DeptEmployee.class); In inClause = criteriaBuilder.in(root.get("title")); for (String title : titles) { inClause.value(title); } criteriaQuery.select(root).where(inClause);
4. Выражение.
В качестве альтернативы мы можем использовать набор перегруженных методов in () из интерфейса Expression :
criteriaQuery.select(root) .where(root.get("title") .in(titles));
В отличие от CriteriaBuilder. in () , Expression.in () принимает набор значений. Как мы видим, это также немного упрощает наш код.
5. Выражения IN с использованием подзапросов
До сих пор мы использовали коллекции с предопределенными значениями. Теперь давайте посмотрим на пример, когда коллекция получается из вывода подзапроса.
Например, мы можем получить всех сотрудников DeptEmployee , принадлежащих к отделу, с указанным ключевым словом в их имени:
Subquery subquery = criteriaQuery.subquery(Department.class); Root 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. Заключение
В этой быстрой статье мы узнали о различных способах выполнения операции IN с помощью Criteria API. Мы также узнали, как использовать Criteria API с подзапросами.
Наконец, полная реализация этого руководства доступна на GitHub.