web-dev-qa-db-ja.com

Hibernate Criteria:エンティティを区別してから制限する

基本的に、アプリケーションが必要とするすべてのデータを返す基準があります。

Criteria criteria = session.createCriteria(Client.class);
criteria.createAlias("address", "address");
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.setFirstResult(init);
criteria.setMaxResults(max);
List<Client> clients = criteria.list();

問題は、クライアント/アドレスの関係が双方向であることです。クライアントには1つのアドレスがあり、1つのアドレスが複数のクライアントに属している可能性があります。

もちろん、テーブルに表示されているいくつかのクライアントのpkに基づいて、「単一」のクライアントオブジェクトを取得したいと思います。

SetFirstResult/setMaxResultsが最初に実行されるため、すでに適用されている制限内でクライアントが重複しています。 (グループ化ではないアプリケーションレベルが使用された後)hibernateは重複したクライアントを削除するため、setMaxResultsで指定された最大値よりも少ないクライアントで終了します。

(投影グループ)でグループ化することはできません。クライアント/アドレスで必要なすべての列が返されるわけではなく、クエリがグループ化しているグループのみです。

(要約すると、私のテーブルにはページごとに100の結果がありますが、重複を破棄した後、100ではなく98の結果があります...)これは、制限:LIMIT 0,100が、休止グループの前に適用され、その後実行する必要があるためです)

12
kandan

「Ashish Thukral」によってリンクされたスレッドで指摘されているように、次の行はこれを解決します。

criteria.setFetchMode("address.clients", FetchMode.SELECT);

これにより、問題の原因となる結合が防止されます。

もちろん、xml構成ファイルからfetch = "join"を削除することは可能ですが、このソリューションは、Beanが取得される可能性がある他の場所には影響しません。

9
kandan

次のようにIDに基づいてクライアントを探している場合。あなたの基準に基づいて、常に1つのクライアントを返すので、最大サイズと初期サイズの必要はありません。

Criteria criteria = getSession().createCriteria(Client.class);
criteria .add(Restrictions.eq("id", yourClientId);
criteria.createAlias("address", "address");
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.setFirstResult(init);
criteria.setMaxResults(max);
List<Client> clients = criteria.list();

次のようにIDに基づいてアドレスを検索する場合。

Criteria criteria = getSession().createCriteria(Client.class);
criteria.createAlias("address", "address");
criteria .add(Restrictions.eq("address.id", yourAddressId);
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
criteria.setFirstResult(init);
criteria.setMaxResults(max);
List<Client> clients = criteria.list();
6
Prabhakaran

私があなたの関係を正しく理解していれば、各クライアントエンティティクラスのアドレスと1つのアドレスにクライアントのリストがあります。したがって、クライアントのリストが必要なだけの場合、何が重要なのでしょうか。

Criteria criteria = session.createCriteria(Client.class);
criteria.setFirstResult(init);
criteria.setMaxResults(max);
List<Client> clients = criteria.list();

エイリアスを作成し、distinct_root_entityを使用するのはなぜですか?そのアドレスを取得する必要がある場合、DAOまたはServiceImplでアクセスすると、Hibernateはとにかく遅延してアドレスをフェッチします。

私が間違っていたら訂正してください。

0
Ashish Thukral