Sql 用于联接子查询的JPA CriteriaBuilder

Sql 用于联接子查询的JPA CriteriaBuilder,sql,hibernate,jpa,Sql,Hibernate,Jpa,我有如下SQL语句: SELECT * FROM person inner join (select max(validityId) as maxID from person group by personId) maxID on maxID.maxID = person.validityid; | personID | validitID | value | ------------------------------------------- | 1 |

我有如下SQL语句:

SELECT * FROM person inner join (select max(validityId) as maxID from person group by personId) maxID on maxID.maxID = person.validityid;
|  personID  |  validitID | value   |
-------------------------------------------
|    1       |    10      | 400     |
|    1       |    11      | 500     |
|    1       |    12      | 600     |
|    2       |    13      | 700     |
|    2       |    14      | 800     |
|    2       |    15      | 900     |
|    4       |    16      | 1000    |
所以它给了我personID“清晰”的一行:

如果我有这样的桌子:

SELECT * FROM person inner join (select max(validityId) as maxID from person group by personId) maxID on maxID.maxID = person.validityid;
|  personID  |  validitID | value   |
-------------------------------------------
|    1       |    10      | 400     |
|    1       |    11      | 500     |
|    1       |    12      | 600     |
|    2       |    13      | 700     |
|    2       |    14      | 800     |
|    2       |    15      | 900     |
|    4       |    16      | 1000    |
它会回来的

|  personID  |  validitID | value   |
-------------------------------------------
|    1       |    12      | 600     |
|    2       |    15      | 900     |
|    4       |    16      | 1000    |
现在我试着用JPA CriteriaBuilder来做这件事

我的第一个想法是子查询:

final CriteriaBuilder cb = this.em.getCriteriaBuilder();
final CriteriaQuery<Person> cq = cb.createQuery(Person.class);
final Root<Person> root = cq.from(Person.class);
cq.select(root);

final Subquery<Long> subquery = cq.subquery(Long.class);
final Root<Person> validityIDSQ = subquery.from(Person.class);
subquery.select(validityIDSQ.get(Person_.validityId));
subquery.groupBy(validityIDSQ.get(Person_.personId));

cb.where(cb.in(root.get(Person_.validityId)).value(subquery));
这是怎么回事


Marko

我认为解决方案比看起来更简单。您忘记在CriteriaBuilder子查询中包含
cb.max()
。下面的代码执行您正在查找的查询

final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
final CriteriaQuery<Person> cq = cb.createQuery(Person.class);
final Root<Person> root = cq.from(Person.class);
cq.select(root);

final Subquery<Integer> subquery = cq.subquery(Integer.class);
final Root<Person> validityIDSQ = subquery.from(Person.class);
subquery.select(cb.max(validityIDSQ.get(Person_.validityID)));
subquery.groupBy(validityIDSQ.get(Person_.personID));

cq.where(cb.in(root.get(Person_.validityID)).value(subquery));

我想你在用Postgres。如果不使用
cd.max()
,它会生成您引用的错误,因为您使用的是GroupBy,而没有使用聚合函数。我在Postgres和MySQL上测试了它。在这两个查询中运行都很有魅力。

您没有在子查询中使用agreegation函数。这不是JPA的问题,甚至SQL也无法通过personId从X group中选择validityId。尝试
subquery.select(cb.sum(validityIDSQ.get(Person.validityId))
您使用的是什么数据库?