使用 Criteria API 查找组中具有最小值的行

问题描述 投票:0回答:1

我正在尝试使用 JPA Criteria API 创建一个过滤器查询,以查找组中具有最低值的所有实体。

例如,给定一个 JPA 实体“学生”映射类似于以下内容的表:

id 名字 年级 班级
1 约翰 1 A
2 吉姆 2 A
3 詹姆斯 4 B
4 乔丹 3 B

我想将其过滤到班上成绩最低的学生,在本例中为

John
Jordan

在 SQL 中,这可以通过像这样的自连接来完成:

SELECT *
FROM students s1
inner join(
select class, Min(grade) as max_grade from students group by class 
) s2 on s1.class = s2.class and s1.grade = s2.max_grade;

但是,我无法找到使用 JPA Criteria API 创建类似的自连接方法的方法。

我不能仅使用 JPQL 来实现此目的,因为必须将此谓词添加到大型现有条件谓词中。

java sql criteria-api
1个回答
0
投票

SQL 查询的编写方式,它将获取班级中成绩等于最低成绩的所有学生如果这不是问题,那么您可以考虑将查询重写为 JPQL,如下所示(接下来我们将讨论 Criteria API:

SELECT s1 FROM Student s1
WHERE s1.grade IN (
  SELECT min(s2.grade) FROM Student s2 GROUP BY s2.class
);

上面的查询也有同样的缺点,它会获取班级中成绩较低的所有学生。但是,在这种形式中,它可以转换为 JPA Criteria API,如下所示,假设 (1) 您已经为方便起见构建了元模型和类型安全以及 (2) 列

class
实际上映射到名为
clazz
的属性,因为
class
是 Java 中的保留名称;变量名称将尽可能与 JPQL 匹配:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Student> query = cb.createQuery(Student.class);
Root<Student> s1 = query.from(Student.class);
Subquery<Integer> subquery = query.subquery(Integer.class);
Root<Student> s2 = subquery.from(Student.class);
subquery
  .select(cb.min(s2.get(Student_.grade)))
  .groupBy(s2.get(Student_.grade));
query
  .select(s1)
  .where(cb.in(s1.get(Student_.grade)).in(subquery));
List<Student> result = em.createQuery(query).getResultList();
© www.soinside.com 2019 - 2024. All rights reserved.