JPA 条件查询组(按仅使用 ID)

2022-09-04 02:26:45

这是一个示例实体:

public class Account{

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

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

现在我创建一个条件查询,将 Join 作为 follwing:

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。

更新
我认为我的问题对你来说不清楚。我的问题不是关于 PostgreSQL 或 Oracle 在 .我的问题是这样的:
我使用在子句中(这意味着我希望休眠使用帐户类型中的所有字段),但是为什么休眠只使用身份字段?如果我只使用标识字段,那么我可以使用以下语句:group bytypeJoingroup bygroup bygroup bygroup by

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

答案 1

JPA/Hibernate 不会自动包含分组依据子句中的所有实体属性,因此您必须手动指定它们:

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

答案 2

如果使用 GROUP BY,Oracle 要求选择列表中的每一列都位于 GROUP BY 中。
PostgreSQL是相同的,除了按主键分组时,它允许您选择任何列。

来自甲骨文文档

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

来自 PostgreSQL docs

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