这是我简单的JPQL:
SELECT s
FROM Site s
GROUP BY s.siteType
siteResult = q.getResultList();
for (Site site : siteResult) {
// loops all sites
}
Run Code Online (Sandbox Code Playgroud)
此查询返回所有站点,包括相同siteType的站点.我正在使用JPA 2.0 Eclipselink.这里有什么不对?
Mik*_*unu 10
这样的查询没有意义.如果使用GROUP BY,则应聚合SELECT中的其他属性.正如JPA规范中所述:
使用GROUP BY时SELECT子句的要求遵循SQL的要求:即SELECT子句中出现的任何项(除了作为聚合函数或作为聚合函数的参数)也必须出现在GROUP BY子句中.在形成组时,为了分组目的,将空值视为相同.
如果您认为查询的SQL对应方:
SELECT s.attr1, attr2, s.siteType
FROM site s
GROUP BY (s.siteType)
Run Code Online (Sandbox Code Playgroud)
你注意到很难想象应该选择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;
}
Run Code Online (Sandbox Code Playgroud)
和两个实例:(id = 1,siteType ="same"),(id = 2,siteType ="same").现在当select的类型是Site本身(或者它的所有属性)并且你按siteType进行分组时,不可能定义结果有一个id值为1或2.这就是为什么你必须使用一些聚合函数(比如AVG,它为您提供剩余属性的平均值(在我们的例子中为id).
在此链接后面:ObjectDB GROUP BY您可以找到GROUP BY和聚合的一些示例.