JPA Criteria查询组仅使用id

时间:2014-12-31 19:53:54

标签: java hibernate jpa group-by criteriaquery

这是一个示例实体:

public class Account{

   @Id
   Long id
   Double remaining;
   @ManyToOne
   AccountType type
}

public class AccountType{
   @Id
   Long id;
   String name;
}  

现在我使用Join创建一个条件查询,如下所示:

CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createquery();
Root<Account> accountRoot = criteriaQuery.from(Account.class);
Join<Account, AccountType> typeJoin = accountRoot.join(Account_.type);

criteriaQuery.multiSelect(
    typeJoin,
    criteriaBuilder.sum(accountRoot.get(Account_.remaining))
);

criteriaQuery.groupBy(typeJoin);
Query query = getEntityManager().createQuery(criteriaQuery);
query.getResultList();  

上面的代码生成如下的Sql命令:

select accType.id, accType.name, sum(acc.remaining)
from account acc join accType on acc.accounttype_id = accType.id
group by accType.id  

以上代码在PosgreSQL中工作但不能在Oracle中运行,因为在其中选择不会出现在group by子句中的accType.name。

更新
我想我的问题并不清楚。我的问题不是关于group by中的PostgreSQL或Oracle行为。我的问题是:
我在typeJoin子句中使用group by(这意味着我希望hibernate在group by中使用AccountType的所有字段),但为什么hibernate只使用group by上的身份字段?如果我只使用group by中的身份字段,那么我可以使用以下语句:

criteriaQuery.groupBy(typeJoin.get(AccountType_.id)) ;

2 个答案:

答案 0 :(得分:9)

JPA / Hibernate不会自动在group by子句中包含所有实体属性,因此您必须手动指定它们:

CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery();
Root<Account> accountRoot = criteriaQuery.from(Account.class);
Join<Account, AccountType> typeJoin = accountRoot.join(Account_.type);

criteriaQuery.multiSelect(
    typeJoin.get("id"),
    typeJoin.get("name"),
    criteriaBuilder.sum(accountRoot.get(Account_.remaining))
);

criteriaQuery.groupBy(typeJoin.get("id"), typeJoin.get("name"));
Query query = getEntityManager().createQuery(criteriaQuery);
query.getResultList();  

答案 1 :(得分:3)

如果使用GROUP BY,Oracle要求选择列表中的每一列都在GROUP BY中。
PostgreSQL是相同的,除非通过主键分组,然后它允许您选择任何列。

来自Oracle docs

  

在包含GROUP BY子句的查询中,select的元素   list可以是聚合函数,GROUP BY表达式,常量或   涉及其中一种的表达。

来自PostgreSQL docs

  

当存在GROUP BY或存在任何聚合函数时,它   对SELECT列表表达式无效以引用未分组   除聚合函数内或未分组列时的列   功能上依赖于分组列,因为它会   否则为一个未分组的人返回一个以上的可能值   柱。如果分组列(或a),则存在功能依赖性   其子集)是包含该表的主键   未经编辑的专栏。