عندما يقوم السبات بمسح الجلسة، كيف يمكن تحديد الكائنات المتسخة في الجلسة؟
سؤال
ما أفهمه عن السبات هو أنه عند تحميل الكائنات من قاعدة البيانات، تتم إضافتها إلى الجلسة.في نقاط مختلفة، اعتمادًا على التكوين الخاص بك، يتم مسح الجلسة.عند هذه النقطة، تتم كتابة الكائنات المعدلة إلى قاعدة البيانات.
كيف يقرر السبات الكائنات "القذرة" والتي يجب كتابتها؟
هل يقوم الوكلاء الذين تم إنشاؤهم بواسطة Hibernate باعتراض التعيينات للحقول وإضافة الكائن إلى القائمة القذرة في الجلسة؟
أم أن السبات ينظر إلى كل كائن في الجلسة ويقارنه بالحالة الأصلية للكائن؟
أو شيء مختلف تماما؟
المحلول
يستخدم Hibernate/يمكنه استخدام إنشاء الكود الثانوي (CGLIB) حتى يعرف أن الحقل متسخ بمجرد الاتصال بأداة الضبط (أو حتى تعيينه إلى الحقل afaict).
يؤدي هذا فورًا إلى وضع علامة على هذا الحقل/الكائن على أنه متسخ، ولكنه لا يقلل من عدد الكائنات التي تحتاج إلى فحص عدم اتساخها أثناء التدفق.كل ما يفعله هو التأثير على تنفيذ org.hibernate.engine.EntityEntry.requiresDirtyCheck()
.هو - هي ما زال يقوم بإجراء مقارنة ميدانية للتحقق من الاتساخ.
أقول ما ورد أعلاه بناءً على عملية بحث حديثة عبر الكود المصدري (3.2.6GA)، مهما كانت المصداقية التي تضيفها.النقاط المثيرة للاهتمام هي:
SessionImpl.flush()
يثيرonFlush()
حدث.SessionImpl.list()
المكالماتautoFlushIfRequired()
مما يؤدي إلىonAutoFlush()
حدث.(على جداول الاهتمام).أي أنه يمكن للاستعلامات استدعاء التدفق.ومن المثير للاهتمام أنه لا يحدث أي تدفق إذا لم تكن هناك معاملة.- كلا الحدثين ينتهي بهما الأمر في نهاية المطاف
AbstractFlushingEventListener.flushEverythingToExecutions()
, ، والذي ينتهي (من بين المواقع الأخرى المثيرة للاهتمام) فيflushEntities()
. - هذا يتكرر على كل كيان في الجلسة (
source.getPersistenceContext().getEntityEntries()
) الدعوةDefaultFlushEntityEventListener.onFlushEntity()
. - ينتهي بك الأمر في النهاية إلى
dirtyCheck()
.تؤدي هذه الطريقة إلى إجراء بعض التحسينات على إشارات CGLIB القذرة، ولكن لا يزال الأمر ينتهي بنا إلى تكرار كل كيان.
نصائح أخرى
يأخذ السبات لقطة لحالة كل كائن يتم تحميله في الجلسة.عند التدفق، تتم مقارنة كل كائن في الجلسة باللقطة المقابلة له لتحديد أي منها متسخ.يتم إصدار عبارات SQL كما هو مطلوب، ويتم تحديث اللقطات لتعكس حالة كائنات الجلسة (النظيفة الآن).
ألقِ نظرة على org.hibernate.event.def.defaultFlushentityEventListener.dirtycheck يذهب كل عنصر في الجلسة إلى هذه الطريقة لتحديد ما إذا كانت قذرة أم لا عن طريق المقارنة مع نسخة غير متوقعة (واحدة من ذاكرة التخزين المؤقت أو واحدة من قاعدة البيانات).
آلية التحقق القذرة الافتراضية في وضع السبات سوف يجتاز الكيانات المرفقة الحالية ويطابق جميع الخصائص مع قيم وقت التحميل الأولية الخاصة بها.
يمكنك تصور هذه العملية بشكل أفضل في الرسم البياني التالي:
هذه الإجابات غير كاملة (في أحسن الأحوال - أنا لست خبيرًا هنا).إذا كان لديك كيان Hib man في جلستك، ولم تفعل شيئًا به، فلا يزال بإمكانك الحصول على تحديث تم إصداره عند استدعاء save() عليه.متى؟عندما تقوم جلسة أخرى بتحديث هذا الكائن بين التحميل () والحفظ ().هنا هو المثال الخاص بي على ذلك: يقوم السبات بتعيين علامة قذرة (وتحديث المشكلات) على الرغم من أن العميل لم يغير القيمة