hibernate 2番目のレベルのキャッシュオブジェクトは怠lazy = falseで、デフォルトのfetch = joinになります、どこにでも文書化されていますか?
-
21-09-2019 - |
質問
私は明らかに文書化されていない問題を経験しています、そして私は理解したいかどうかを理解したい
- 私は何か悪いことをした
- 誰かが同じ問題に遭遇しましたか?
- それは本当にどこにも文書化されていませんか?それとも私は何かを逃しましたか?
動作は、これが次のマッピングを想定しています
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar"/>
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
まず、背景として、 フェッチ 多くの関係の属性はあるべきです」選択する「、これは少なくとも文書化されているものです(見つけたらここにリンクを追加します)
ただし、参照されるクラスが怠lazy = "true"である場合にのみ、これは真実です!
したがって、どうやら上記のマッピングはこれに翻訳されています(barは怠zy = "false"であるため):
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
さて、なぜそれが問題になるのでしょうか? 2つの選択の代わりに、hibernateは「親」を備えた単一の選択に非怠zyな参照をロードします(単一の選択でバーをbarにロードします)
オブジェクトは怠zyではないので、これは実際に理にかなっています。ロードしてみませんか?
答えはこれです:バーが2レベルのキャッシュにある場合はどうなりますか?
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
<cache usage="transactional" />
...
</class>
そして、それに対する答えは - 何も変わらない!
どうやら、冬眠はこのタイプのオブジェクトをロードすべきではないことを理解するのに十分賢いと仮定するでしょうが、デフォルトのフェッチがSelectから結合に変更されたため、Hibernateには選択肢がありません(実際のテーブルに参加することはできません2番目のレベルのキャッシュ、まだ)
したがって、hibernateはそれが言われていることを行い、結合を使用してデータベースからオブジェクトを取得します。
私が見つけた解決策は、文字通りマッピングをfetch = "select"に変更することです
Barの2番目のSelectが進みようとしているとき、Hibernateはデータベースに移動してはならないことを理解し、キャッシュから取得します。そして、1つのクエリのみが実行されます(ウォームアップ後)
解決
私は同じ問題に遭遇しましたが、キャッシュされるすべての多くの関係をマークしていることに気付きました fetch="select"
. 。クエリが構築された時点で、Hibernateは、Barの要求されたインスタンスが第2レベルのキャッシュにあるかどうかを知ることができません(Fooがキャッシュされていないと仮定)。