web-dev-qa-db-ja.com

JPA CriteriaクエリグループはIDのみを使用します

これはサンプルエンティティです。

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で機能しますが、グループ化句に表示されないaccType.nameを選択するため、Oracleでは実行できません。

更新
私の質問はあなたにとって明確ではないと思います。私の質問は、group byでのPostgreSQLまたはOracleの動作に関するものではありません。私の質問はこれです:
私はgroup by句でtypeJoinを使用しています(これは、Hibernateがgroup byでAccountTypeのすべてのフィールドを使用することを期待していることを意味します)が、Hibernateがgroup bygroup byのIDフィールドのみを使用する場合は、次のステートメントを使用できます。

criteriaQuery.groupBy(typeJoin.get(AccountType_.id)) ;
11
Rasoul Taheri

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();  
9
Vlad Mihalcea

GROUP BYを使用する場合、Oracleでは、選択リストのすべての列がGROUPBYに含まれている必要があります。
主キーでグループ化する場合を除いて、PostgreSQLは同じです。これにより、任意の列を選択できます。

From Oracle docs

GROUP BY句を含むクエリでは、選択リストの要素は、集計関数、GROUP BY式、定数、またはこれらのいずれかを含む式にすることができます。

から PostgreSQLドキュメント

GROUP BYが存在する場合、または集計関数が存在する場合、集計関数内を除いて、またはグループ化されていない列がグループ化された列に機能的に依存している場合を除いて、SELECTリスト式がグループ化されていない列を参照することは無効です。グループ化されていない列に対して返される可能性のある1つの値よりも大きい。グループ化された列(またはそのサブセット)が、グループ化されていない列を含むテーブルの主キーである場合、機能従属性が存在します。

4
outdev