使用groupBy时,JPA2 Criteria API会创建无效的SQL

时间:2012-09-13 09:36:43

标签: postgresql jpa-2.0 criteria-api hibernate-criteria

带有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而不是类型

进行分组

按照

错误消息的建议按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);

也会导致同样的错误。

有谁知道如何解决这个问题?

2 个答案:

答案 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)

我已在EclipseLinkMySql上测试了您的第一个示例。它没有抛出任何异常,如果我没有误解你的目标,那么结果查询就是你要找的:

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