【问题标题】:JPA2 Criteria API creates invalid SQL when using groupByJPA2 Criteria API 在使用 groupBy 时创建无效 SQL
【发布时间】:2012-09-13 09:36:43
【问题描述】:

带有 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);

也会导致同样的错误。

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

【问题讨论】:

  • 您不应该在groupBy 子句中使用object.id 吗? groupBy(object) 在 JPA 中是否隐含表示“按主键分组”?还是“按所有字段分组”?你能说明这个简化的例子产生的错误吗?
  • 我添加了一个按对象 id 分组的示例,这会导致相同的错误。此错误消息出现在所有提到的示例中。

标签: postgresql jpa-2.0 criteria-api


【解决方案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 上提交问题报告。链接到这里;一旦有一个完整且可运行的测试用例,我就会试一试。

另外,您确定错误消息在您更改的测试用例中保持完全相同相同,它没有引用不同编号的别名或任何东西吗?

【讨论】:

  • 感谢您的帮助!我使用所需的测试用例创建了 JIRA:hibernate.onjira.com/browse/JPA-34
  • @Stephan 我不知道你现在是否可以更改它,但它确实应该在HIBERNATE 而不是JPA 下提交。 JPA 项目用于规范。
  • @Stephan 我已将其重新归档为hibernate.onjira.com/browse/HHH-7611;可能想将自己添加为观察者。
  • @Stephan 当你观看它时,也给它投票。顺便说一句,将测试用例转换为 EclipseLink 并且更简单的两个测试通过但 testGroupByWithSum 也失败了。我不相信testGroupByWithSum 是正确的。您可以对 EclipseLink 转换的测试进行 DL 并使用它,看看您是否可以让 testGroupByWithSum 工作?
  • 我将错误报告移至 HHH。是否应该将新的指定为重复项?
【解决方案2】:

我已经在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

【讨论】:

    猜你喜欢
    • 2015-11-23
    • 2012-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多