首页 > 解决方案 > JPA 标准按相关实体过滤,无需连接

问题描述

我想知道如何使用 JPA Criteria API 通过相关实体的外键过滤实体。

假设我有以下两个实体:

public class Employee {
    @Id
    private Long id;
    ...
    @ManyToOne
    private Department department;
    ...
}

public class Department {
    @Id
    private Long id;
}

我想查询ids(1,2,3)部门下的员工。

我能够使用 Hibernate 的废弃标准来做到这一点,并且想知道如何使用 JPA Criteria predicate without join (root.join)来做到这一点。我不需要任何连接或子查询是合乎逻辑的,因为可以从一个表中获取所需的结果:

select e.* from employee e where e.department_id in (1,2,3)

** 更新 **

我的问题是——对于 JPA 标准来说是新的,并且来自已弃用的 Hibernate 标准——我使用了 CriteriaBuilder 中的所有 API,例如 (equal, notEqual, isNull, like, .....); 并且,因此,使用了CriteriaBuilder.In(experssion).in(values). 但是,如@frank 的回答所示,我发现对于 IN 的使用,我将使用Root.get(<attr>).in(<values>)

CriteriaBuilder.in也可以使用但不同:

In<Object> inClause = criteriaBuilder.in(root.get(<attr>);
for (Long id : ids) {
    inClause.value(id);
}

但是,当然,第一个解决方案更容易。

标签: javahibernatejpajpa-2.2

解决方案


Set<Integer> departments = new HashSet<Integer>();
departments.add(1);
departments.add(2);
departments.add(3);

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
Root<Employee> r = cq.from(Employee.class);
cq.select(r).where(r.get(Employee_.department).get(Department_.id).in(departments));
TypedQuery<Employee> query = em.createQuery(cq);
List<Employee> result = query.getResultList();

推荐阅读