كائنات ذاكرة التخزين المؤقت من المستوى الثاني من Hibernate كسول = خطأ ، تؤدي إلى جلب افتراضي = انضمام ، هل تم توثيقه في أي مكان؟
-
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>
أولاً ، كخلفية ، القيمة الافتراضية لـ Hibernate لـ أحضر يجب أن تكون السمة على علاقة كثيرة "تحديد"، هذا على الأقل ما هو موثق (سأضيف الرابط هنا عندما أجده)
ومع ذلك ، يبدو أن هذا صحيح فقط إذا كانت الفئة المرجعية كسول = "صحيح"!
لذلك يبدو أن رسم الخرائط أعلاه تترجم إلى هذا (لأن الشريط كسول = "خطأ"):
<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 بتحميل المرجع غير الكسول في مجموعة مختارة واحدة مع "الأصل" (تحميل Foo مع شريط في اختيار واحد)
هذا منطقي في الواقع ، لأن الكائن ليس كسولًا ، لماذا لا يتم تحميله؟
الجواب هذا: ماذا يحدث إذا كان بار في ذاكرة التخزين المؤقت من المستوى الثاني؟
<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 ليس لديه خيار (لا يمكنك الانضمام إلى جدول حقيقي مع ذاكرة التخزين المؤقت من المستوى الثاني ، حتى الآن)
لذا فإن السبات يفعل ما يقال له ، ويستخدم صلة لجلب كائن من قاعدة البيانات حيث يوجد بالفعل في ذاكرة التخزين المؤقت للمستوى الثاني
الحل الذي وجدته هو تغيير التعيين حرفيًا لجلب = "حدد"
الآن عندما يكون الاختيار الثاني لـ BAR على وشك الذهاب ، يفهم Hibernate أنه يجب ألا يذهب إلى قاعدة البيانات ، ويحضرها من ذاكرة التخزين المؤقت. وسيتم تنفيذ استعلام واحد فقط (بعد الاحماء)
المحلول
لقد واجهت نفس المشكلة ، ووجدت نفسي أحدد جميع العلاقات التي سيتم تخزينها مؤقتًا fetch="select"
. في الوقت الذي يتم فيه بناء الاستعلام ، لا يمكن لـ Hibernate معرفة ما إذا كان مثيل الشريط المطلوب في ذاكرة التخزين المؤقت من المستوى الثاني أم لا (على افتراض أن FOO ليس في المخزونات).