2014-12-31 10 views
6

これはサンプルのエンティティである:JPA基準のクエリグループIDのみ

public class Account{ 

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

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

今、私は基準のクエリを作成するには、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のコードの作業の上にそれにdoesnのaccType.nameを選択するため、オラクルでは実行できません。次group by節に現れません。

更新
私の質問はあなたにとってはっきりしないと思います。私の質問は、group byのPostgreSQLまたはOracleの動作に関するものではありません。私はgroup by句(これは私がgroup byでの使用にAccountTypeのすべてのフィールドを休止期待する意味)でtypeJoinを使用していますが、なぜ単にgroup by上のIDフィールドを使用して休止状態
:私の質問はこれですか?私はgroup byでちょうどアイデンティティフィールドを使用するならば、私は、次のステートメントを使用することができます。

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

答えて

6

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

これはお勧めできません。このソリューションではいつでもAccountTypeが変更されました。ほとんどの場合、すべてのクエリが変更されます。もちろん私は反射でそれを処理することができますが、私はそれのためのよりよい解決策でなければならないと思う。休止状態がすべてのエンティティプロパティを含むことはできませんか? –

+0

accountType.idを指定し、その後に2次キャッシュを使用してロードすることができます。 –

+0

もちろん、JPAメタモデルを使用してエンティティタイプのすべての属性を取得し、それらをジェネリックであるグループに入れることもできます。 –

3

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

GROUP BY句を含むクエリで

Oracle docsから選択 リストの要素は、集約関数、これらのいずれかを含む式、定数、または 式BY基であることができます。 PostgreSQL docsから

GROUP BYが存在する、または任意の集約関数が存在する場合、SELECTリスト式は、集約関数内、または時を除いてグループ化されていない 列を参照するために、それ が有効でありません はグループ化されていない 列に対して複数の可能な値を返すため、グループ化されていない列 はグループ化された列に機能的に依存しています。グループ化された列(または のサブセット)が、 グループ化されていない列を含むテーブルの主キーである場合、機能的な依存関係が存在します。