Sql 用于联接子查询的JPA CriteriaBuilder
我有如下SQL语句: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 |
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))
您使用的是什么数据库?