左の結合基準を使用する場合の冬眠児童コレクションリミテッド
-
24-10-2019 - |
質問
Hibernate基準を使用する場合、結合タイプを変更するだけで、ルートドメインクラスの子コレクションの結果に影響します。
たとえば、クラスの親を持つことは、次のデータを使用して、クラスの子と1対多くの関係を持っています。
Parent | id | Name | | 1 | Parent 1 | Child | id | parent_id | Name | | 1 | 1 | Child1 | | 2 | 1 | Child2 |
次の冬眠基準を使用すると、1つの親の行が返され、子コレクションにアクセスすると、2つの行が返されます。
session.createCriteria(Parent.class)
.createCriteria('child', CriteriaSpecification.INNER_JOIN)
.add( Restrictions.eq( 'name', 'Child1' ) )
.list()
ただし、上記のコードを左結合で変更すると、1つの親の行が返されますが、子コレクションにアクセスするときに一致する子の行のみが返されます。
session.createCriteria(Parent.class)
.createCriteria('child', CriteriaSpecification.LEFT_JOIN)
.add( Restrictions.eq( 'name', 'Child1' ) )
.list()
なぜこの副作用が発生するのですか?意図した結果に応じて、この副作用を使用または回避することについていくつかの議論を見つけましたが、そもそもなぜそこにあるのか、そしてそれが意図されていたかどうかについては何もありませんでした。最も近い直接的な質問は、古い古い欠陥です(http://opensource.atlassian.com/projects/hibernate/browse/hhh-3872).
- 編集3/24:データを修正 *
解決
この問題はここで説明されており、冬眠3.6で修正されているようです
他のヒント
私はこれを試しました:このクエリを実行したとき、その後parent.getChildren()を呼び出すようになったとき:
- 左結合:親と1つの一致する子供を含む1つのクエリが実行されます。GetChildren()を呼び出すときに後続のクエリは実行されません
- inner_join:2つのクエリが実行されます:1つは、getChildren()を呼び出すときに子供と一致する親を見つけ、もう1つを見つけることができます。
したがって、left_joinを呼び出すと、子供(この場合は一致する子供たち)が熱心に獲得されており、親の子供のコレクションはすでに人口がかかっているようです。ただし、Inner_Joinの場合、このコレクションはプロキシとしてマークされ、getChildren()を呼び出すときに初期化されます。この2番目のクエリは、もちろん名前の制限を考慮しなくなり、親のためにすべての子供を取得するだけです。
これは「内部」で発生するように見えます。つまり、結合タイプは、冬眠が結果をどのように扱うかに影響します。左と内部の結合の間の生成されたSQLはわずかに異なりますが(私のテストでは、parent.idとchild.idはSELECT句で2回でした)、DBブラウザーでSQLを実行するときに結果が同じです。
私はこれがバグかどうかを判断するのに十分な経験がありませんが、それはそれのようには感じません。