首页 文章

JPA Criteria查询组仅使用id

提问于
浏览
10

这是一个示例实体:

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 .

update
我认为我的问题不是't clear for you. My question isn' t关于PostgreSQL或_2730113中的Oracle行为 . 我的问题是:
我在 group by 子句中使用 typeJoin (这意味着我希望hibernate在 group by 中使用AccountType的所有字段),但为什么hibernate只使用 group by 上的标识字段?如果我在 group by 中只使用身份字段,那么我可以使用以下语句:

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

2 回答

  • 8

    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();
    
  • 3

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

    来自Oracle docs

    在包含GROUP BY子句的查询中,选择列表的元素可以是聚合函数,GROUP BY表达式,常量或涉及其中一个的表达式 .

    来自PostgreSQL docs

    当存在GROUP BY或存在任何聚合函数时,SELECT列表表达式无效以引用未聚合的列,但在聚合函数中或未分组的列在功能上依赖于分组列时,否则将无效为未分组的列返回多个可能的值 . 如果分组列(或其子集)是包含未分组列的表的主键,则存在功能依赖性 .

相关问题