这是我简单的JPQL:
SELECT s
FROM Site s
GROUP BY s.siteType
siteResult = q.getResultList();
for (Site site : siteResult) {
// loops all sites
}
此查询返回所有网站,包括相同siteType的网站。 我使用的是JPA 2.0 Eclipselink。 这有什么不对吗?
答案 0 :(得分:10)
这样的查询没有意义。如果使用GROUP BY,则应聚合SELECT中的其他属性。正如JPA规范中所述:
使用GROUP BY时对SELECT子句的要求如下 SQL的那些:即SELECT子句中出现的任何项 (作为聚合函数或作为聚合的参数除外) function)也必须出现在GROUP BY子句中。在形成 组,空值被视为相同的分组目的。
如果您认为查询的SQL对应部分:
SELECT s.attr1, attr2, s.siteType
FROM site s
GROUP BY (s.siteType)
你注意到很难想象应该选择attr1和attr2的哪个可能值。
在这种情况下,带有derby的EclipseLink只会将GROUP BY从查询中删除,这当然是处理无效JPQL的有点可疑方法。我更喜欢Hibernate + MySQL如何使用这样一个无效的JPQL,它失败并且有非常明确的错误信息:
java.sql.SQLSyntaxErrorException:分组查询的SELECT列表 包含至少一个无效表达式。如果SELECT列表具有GROUP BY,列表可能只包含有效的分组表达式并且有效 聚合表达式。
回答评论: 一个站点也可能包含除siteType之外的其他属性。让我们使用以下示例:
public class Site {
int id;
String siteType;
}
和两个实例:(id = 1,siteType =“same”),(id = 2,siteType =“same”)。现在当select的类型是Site本身(或者它的所有属性)并且你按siteType进行分组时,不可能定义结果有一个id值为1或2.这就是为什么你必须使用一些聚合函数(如AVG,它为您提供剩余属性的平均值(在我们的例子中为id)。
在此链接后面:ObjectDB GROUP BY您可以找到GROUP BY和聚合的一些示例。