带有Criteria API的JPA2似乎为PostgreSQL生成了无效的SQL。对于此代码:
Root<DBObjectAccessCounter> from = query.from(DBObjectAccessCounter.class);
Path<DBObject> object = from.get(DBObjectAccessCounter_.object);
Expression<Long> sum = builder.sumAsLong(from.get(DBObjectAccessCounter_.count));
query.multiselect(object, sum).groupBy(object);
我得到以下异常:
ERROR: column "dbobject1_.id" must appear in the GROUP BY
clause or be used in an aggregate function
生成的SQL是:
select dbobjectac0_.object_id as col_0_0_,
sum(dbobjectac0_.count) as col_1_0_, dbobject1_.id as id1001_,
dbobject1_.name as name1013_,
dbobject1_.lastChanged as lastChan2_1013_,
dbobject1_.type_id as type3_1013_
from DBObjectAccessCounter dbobjectac0_
inner join DBObject dbobject1_
on dbobjectac0_.object_id=dbobject1_.id
group by dbobjectac0_.object_id
显然,select语句的第一项(dbobjectac0_.object_id)与group by子句不匹配。
它甚至不适用于这个简单的例子:
Root<DBObjectAccessCounter> from = query.from(DBObjectAccessCounter.class);
Path<DBObject> object = from.get(DBObjectAccessCounter_.object);
query.select(object).groupBy(object);
返回
select dbobject1_.id as id924_, dbobject1_.name as name933_,
dbobject1_.lastChanged as lastChan2_933_,
dbobject1_.type_id as type3_933_
from DBObjectAccessCounter dbobjectac0_
inner join DBObject dbobject1_
on dbobjectac0_.object_id=dbobject1_.id
group by dbobjectac0_.object_id
并产生与上述相同的错误。
按照
错误消息的建议按ID进行分组Root<DBObjectAccessCounter> from = query.from(DBObjectAccessCounter.class);
Path<DBObject> object = from.get(DBObjectAccessCounter_.object);
Path<Long> objectId = from.get(DBObjectAccessCounter_.object).get(DBObject_.id);
query.select(object).groupBy(objectId);
也会导致同样的错误。
有谁知道如何解决这个问题?
答案 0 :(得分:1)
PostgreSQL 9.2及更高版本在检测“隐式分组”列方面有所改进,即您将主键放在group by
中的位置,因此可以在SELECT列表中引用该表中的所有字段。以前的版本没有检测到这一点,因此SELECT id, somefield FROM sometable GROUP BY id
会导致Column sometable.somefield must appear in the GROUP BY clause
。在较新的版本中,Pg将检测到somefield
被隐式分组,因为包含id
并允许此查询运行。
不幸的是,我不确定这会解决你的问题;你的问题是你是按照连接条件另一边的密钥进行分组,我怀疑Pg会将它识别为PK,因为该列没有标记为。
我建议您编写一个自包含的测试用例并在Hibernate JIRA上提交问题报告。链接到这里;一旦有一个完整且可运行的测试用例,我就会有一个游戏并看到。
此外,您确定错误消息在更改的测试用例中完全相同,它不是指不同编号的别名或其他内容吗?
答案 1 :(得分:0)
我已在EclipseLink
和MySql
上测试了您的第一个示例。它没有抛出任何异常,如果我没有误解你的目标,那么结果查询就是你要找的:
SELECT t0.id, t0.name, SUM(t1.count)
FROM dbobject t0, dbobjectaccesscounter t1
WHERE (t0.id = t1.object_id) GROUP BY t0.id, t0.name