البحث الرئيسي في هذه المقالة هو مستوى السبات في SETATE_FLUSH. المقدمة والأمثلة المحددة هي كما يلي.
دعونا نلقي نظرة على بعض المفاهيم أولاً:
1. القراءة القذرة: تسمى القراءة القذرة أيضًا قراءة البيانات غير الصالحة. وهذا يعني أنه أثناء الوصول إلى قاعدة البيانات ، يقوم الشيء T1 بتعديل قيمة معينة ، ثم يقرأ الشيء T2 القيمة. بعد ذلك ، يلغي T1 تعديل القيمة لسبب ما ، مما يؤدي إلى أن تكون البيانات التي يقرأها T2 غير صالحة. القراءة القذرة تعني أنه عندما يقوم شيء ما بالوصول إلى البيانات وتعديل البيانات ، ولم يتم إرسال هذا التعديل إلى قاعدة البيانات ، فإن هناك شيئًا آخر يصل أيضًا إلى هذه البيانات ثم يستخدم هذه البيانات. نظرًا لأن هذه البيانات لا تزال غير مقدمة ، فإن البيانات التي يقرأها شيء آخر هي البيانات القذرة ، والعمليات التي يتم تنفيذها بناءً على البيانات القذرة غير صحيحة.
2. لا تتكرر القراءة: على سبيل المثال ، عندما كنت أقرأ منشورًا ، كانت البيانات التي وجدتها هي Zhang San و Li Si. بعد ذلك ، بعد أن تم تحديثها ، وجدت أن Zhang San الأولي أصبح Zhang BA. هذه هي القراءة غير القابلة للتكرار ، لأن البيانات التي قرأتها لم تتكرر.
3. قراءة الخيال: عندما كنت أبحث عن البيانات ، بدأت في العثور على 3 سجلات. عندما قمت بتحديثها ، وجدت أن السجلات أصبحت 8. هذه هي القراءة الخيالية.
4. إرسال القراءة: يمكنك القراءة فقط بعد التقديم. أوراكل الافتراضية لهذا. لا توجد قراءة قذرة بهذه الطريقة.
5. التكرار: من الواضح أنه عكس القراءة غير القابلة للتكرار. يمكن أن يتجنب القراءة غير القابلة للتكرار ، ولكن هذا لا يمكن أن يتجنب القراءة الوهمية.
6. التسلسل: هذه الطريقة صارمة للغاية. من حيث العلمان ، عندما أفعل شيئًا ، لا يمكن لأحد أن يفعل ذلك. إنه آمن للغاية ، لكنه غير فعال للغاية.
أدناه نستخدم أمثلة عملية لفهم تطبيق إزالة ذاكرة التخزين المؤقت للإسبات.
ترتبط قاعدة بيانات رسم الخرائط السطحية باستراتيجية توليد المفاتيح الأساسية.
أمثلة على توليد المفاتيح الأولية في UUID:
مستخدم الفئة العامة {private string uid ؛ private uname uname ؛ عيد ميلاد خاص ؛ سلسلة عامة getuid () {return uid ؛} public void setuid (string uid) {this.uid = uid ؛} السلسلة العامة getUname () {return uname ؛ setbirthday (تاريخ عيد ميلاد) {this.birthday = عيد ميلاد ؛}}user.hbm.xml:
<؟ package = "com.lixue.bean"> <!-يمثل اسم عقدة الفئة اسم الفئة للكيان ، ويمثل الجدول اسم الكيان المعين إلى الجدول في قاعدة البيانات-> <class name = "user" table = "t_user" name = "عيد ميلاد"/> </class> </hibernate mapping>
طريقة الاختبار:
/ ***اختبر استراتيجية توليد المفاتيح الأساسية UUID*/ public void testSave1 () {/*SESSION SETATE والأشياء*/ جلسة الجلسة = NULL ؛ معاملة المعاملة = فارغة ؛ حاول { /*الحصول على الجلسة والأشياء* / الجلسة = hibernateutils.getSession () ؛ المعاملة = session.begintransaction () ؛ /*إنشاء المستخدم*/ user user = new user () ؛ user.setUname ("xi jinping") ؛ user.setbirthday (date ()) ؛ / *** نظرًا لأن استراتيجية توليد المفاتيح الأساسية للمستخدم هي UUID ، بعد استدعاء SAVE ، فإنها تتضمن فقط المستخدم في إدارة الجلسة* لن يتم إصدار بيان الإدراج ، ولكن تم إنشاء المعرف ، وحالة الوجود في persistenceContex /** * استدعاء تدفق ، سوف تنظف السبات ذاكرة التخزين المؤقت (أدخل الكائنات في المجموعة المؤقتة في الجلسة-> الإدراج في قاعدة البيانات ، ومسح المجموعة المؤقتة) * في هذا الوقت ، لا يمكن رؤية البيانات في قاعدة البيانات ، ولكن إذا تم تعيين مستوى العزلة في حالة عدم وجودها في حالة عدم تقديمها إلى القراءة. session.flush () ؛ /** * إرسال الأشياء * بشكل افتراضي ، ستؤدي عملية الالتزام ذاكرة التخزين المؤقت للتنظيف ، * بحيث لا يمكن إعادة البيانات بعد استدعاء Flush دون عرض * Commit * Transaction.Commit () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Transaction.Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }} يمكننا تصحيح البرنامج من خلال نقاط التوقف:
1. بما أن المعدل الجانبي لتوليد المفتاح الأساسي للمستخدم هو UUID ، بعد استدعاء طريقة SAVE () ، لا يمكن تضمين كائن المستخدم إلا في إدارة الجلسة ، ولن يتم إصدار بيان الإدراج ، ولكن تم إنشاء المعرف (ملاحظة: هناك مكانان مهمان للغاية بعد الادخار. persistenceContext-> EntityentRies-> map-> table-> عنصر صفيف معين-يخزن القيمة الكائن. كما هو موضح في الصورة:
2. بعد استدعاء طريقة Flush () ، سيتم تعيين قيمة ActionQueue المؤقتة في الجلسة ، ثم يتم ضبط قيمة existsIndatabase في persistenceContex بيانات. بعد استدعاء طريقة الالتزام () ، هناك بيانات في قاعدة البيانات.
مثال على توليد المفاتيح الأولية بالطريقة الأصلية:
الفئة العامة user1 {private integer uid ؛ private uname uname ؛ عيد ميلاد خاص ؛ integer public integer getUid () {return uid ؛} public void setuid (integer uid) {this.uid = uid ؛} public getUname () {return uname ؛ عيد ميلاد ؛} public void setbirthday (تاريخ عيد ميلاد) {this.birthday = عيد ميلاد ؛}}user1.hbm.xml:
<؟ package = "com.lixue.bean"> <!-يمثل اسم عقدة الفئة اسم الفئة للكيان (تذكر تعديل اسم الفئة عند تعيين ملف التعيين ، وإلا سيحدث خطأ) ، يمثل الجدول اسم الكيان المعين إلى الجدول في قاعدة البيانات-> <class name = "user1" table = "t_user1" </id> <property name = "uname"/> <property name = "birthday"/> </slass> </hibernate-mapping>
طريقة الاختبار:
/ ***اختبار استراتيجية توليد المفتاح الأساسي الأصلي*/ public void testSave2 () {/*SENTEM SETATE والأشياء*/ جلسة الجلسة = NULL ؛ معاملة المعاملة = فارغة ؛ حاول { /*الحصول على الجلسة والأشياء* / الجلسة = hibernateutils.getSession () ؛ المعاملة = session.begintransaction () ؛ /*إنشاء مستخدم*/ user1 user = جديد user1 () ؛ user.setUname ("li keqiang") ؛ user.setbirthday (date ()) ؛ / *** نظرًا لأن استراتيجية توليد المفاتيح الأساسية للمستخدم 1 هي أصلية ، بعد الاتصال بالجلسة. Transaction.Commit () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Transaction.Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }} تصحيح البرنامج عبر نقطة الإيقاف:
1. نظرًا لأن استراتيجية توليد المفاتيح الأساسية هي أصلية ، بعد استدعاء طريقة Save () ، سيتم تنفيذ عبارة INSERT ، وسيتم مسح البيانات الموجودة في كائن المجموعة المؤقت ، وسيتم إرجاع المعرف الذي تم إنشاؤه بواسطة قاعدة البيانات.
2. قم بتضمين الكائن في إدارة الجلسة ، وقم بتعديل خاصية existsindatabase في persistenceContext إلى TRUE (يشير إلى أن هناك بيانات مقابلة في قاعدة البيانات ، ولكن لا يمكن رؤيتها بسبب منطقة العزلة).
دعنا نختبر طريقة أخرى من السبات ، وهي إخلاء () ، مما يعني طرد الكائن من الجلسة.
بالنسبة للبرنامج الذي يولد استراتيجية uuid الرئيسية الرئيسية ، إليك طريقة اختبار:
/ ***اختبر استراتيجية توليد المفاتيح الأساسية UUID*/ public void testSave3 () {/*SESSION SETATE والأشياء*/ جلسة الجلسة = NULL ؛ معاملة المعاملة = فارغة ؛ حاول { /*الحصول على الجلسة والأشياء* / الجلسة = hibernateutils.getSession () ؛ المعاملة = session.begintransaction () ؛ /*إنشاء المستخدم*/ user user = new user () ؛ user.setUname ("Hu Jintao") ؛ user.setbirthday (date ()) ؛ /*** لأن استراتيجية توليد المفاتيح الأساسية للمستخدم هي UUID ، بعد استدعاء الحفظ ، فقط دمج المستخدم في إدارة الجلسة* لن تصدر عبارة INSERT ، ولكن تم إنشاء المعرف. حالة existsIndateBase في الجلسة خاطئة */ session.save (المستخدم) ؛ /*إخلاء كائن المستخدم من الجلسة ، أي ، تم طرده من خاصية EntityentRies الخاصة بـ persistenceContext*/ session.vict (المستخدم) ؛ /** * لا يمكن إرسالها بنجاح ، لأنه عندما يقوم Hibernate بتنظيف ذاكرة التخزين المؤقت ، يتم إدراج كائن المستخدم من الجلسات التي تدرج المجموعة المؤقتة لإدراج * بعد العملية ، يجب أن يتم تحديث EviceNsindatabase في خاصية EntityentRies إلى True ، ونحن لا يمكن أن يطلق على الطريقة الشريرة. Transaction.Commit () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Transaction.Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }} تصحيح الأخطاء عبر نقاط التوقف:
1. منذ استخدام استراتيجية توليد المفاتيح الأساسية لـ UUID ، لن يتم إرسال عبارة INSERT بعد استدعاء طريقة SAVE (). يتم تضمين الكائن في إدارة الجلسة. تم إنشاء المعرف وليس هناك بيانات مقابلة في قاعدة البيانات (أي ، قيمة سمة AXISTINGINDATABASE خاطئة).
2. بعد استدعاء ExiCt () ، قم بطرد كائن المستخدم من الجلسة ، أي ، تم طرده من خاصية EntityentRies الخاصة بـ persistenceContext.
3. عندما أدعو طريقة الالتزام () مرة أخرى ، سنجد أنه لا يمكن حفظ بياناتنا لأنه في البداية كانت خاصية وجودنا FerveAndatabase خاطئة ، أي أنه لا توجد بيانات مقابلة في قاعدة البيانات. ثم أطلقنا على Evil () لحذف جميع خصائص الكائنات في persistenceContext (تم تضمين خاصية الوجود isindatabase) ، ولكن لم يتم حذف البيانات المخزنة المؤقتة في Actionqueue. عندما نسمي طريقة الالتزام () ، سنقوم أولاً بالاتصال بطريقة Flush () ضمنيًا. كما تم ذكر وظيفة هذه الطريقة من قبل. سيقوم بإدراج الكائن المؤقت في ActionQueue ، ثم تعيين قيمة خاصية existsindatabase في persistenceContext إلى true. لسوء الحظ ، لا توجد خاصية موجودة في persistencecontext ، لذلك سيحدث خطأ ، مما يؤدي إلى عدم القدرة على الادخار.
للقيام بذلك ، نقوم بتحسين الإجراء أعلاه:
/ ***اختبر استراتيجية توليد المفاتيح الأساسية UUID*/ public void testSave4 () {/*SESSION SETATE والأشياء*/ جلسة الجلسة = NULL ؛ معاملة المعاملة = فارغة ؛ حاول { /*الحصول على الجلسة والأشياء* / الجلسة = hibernateutils.getSession () ؛ المعاملة = session.begintransaction () ؛ /*إنشاء المستخدم*/ user user = new user () ؛ user.setUname ("Hu Jintao") ؛ user.setbirthday (date ()) ؛ /*** لأن استراتيجية توليد المفاتيح الأساسية للمستخدم هي UUID ، بعد استدعاء الحفظ ، فقط دمج المستخدم في إدارة الجلسة* لن تصدر عبارة INSERT ، ولكن تم إنشاء المعرف. حالة الوجود في persistencecontext خاطئة */ session.save (المستخدم) ؛ / ***بعد التدفق ، ستقوم Hibernate بتنظيف ذاكرة التخزين المؤقت ، وإنقاذ كائن المستخدم إلى قاعدة البيانات ، وقم بمسح كائن المستخدم في الإدراج في الجلسة*، وتعيين حالة existsindatabase في persistenceContext إلى true*/ session.flush () ؛ / * إخلاء كائن المستخدم من الجلسة ، أي ، تم طرده من خاصية EntityentRies الخاصة بـ PersistenceContext */ session.vict (المستخدم) ؛ / *** يمكن تقديمها بنجاح لأن Hibernate لا يمكن أن يكون في مجموعة إدراج الجلسة عند تنظيف ذاكرة التخزين المؤقت* تم العثور على كائن المستخدم (تم مسحها عند استدعاء Flush) ، لذلك لن يتم إصدار بيان الإدراج ، ولن يتم تحديث حالة ExistIndatabase في الجلسة*/ المعاملات. } catch (استثناء e) {E.PrintStackTrace () ؛ Transaction.Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }} ملاحظة: بعد الحفظ ، نسمي طريقة Flush () ثم استدعاء طريقة Evict () بعد البرنامج المعدل.
تصحيح الأخطاء عبر نقاط التوقف:
1. لأنه لا يزال استراتيجية توليد UUID ، بعد استدعاء Save ، لن يتم إصدار بيان الإدراج ، ولكن يتم تضمين الكائن في إدارة الجلسة. خاصية existsindatabase في persistenceContext خاطئة.
2. بعد الاتصال Save () ، نسمي طريقة Flush () مرة أخرى. تتمثل وظيفة هذه الطريقة في تنظيف ذاكرة التخزين المؤقت ، أي إصدار عبارة إدراج ، وإدراج الكائن المؤقت في الإدراج في الجلسة في قاعدة البيانات ، ثم قم بمسح المجموعة المؤقتة ، وتعيين خاصية existsIndatabase في persistenceContext to true.
3. بعد استدعاء Flush () ، يتم استدعاء طريقة Evict (). تتمثل وظيفتها في مسح كائن المستخدم من الجلسة ، أي لمسح خاصية EntityentRies الخاصة بـ persistenceContext.
4. بعد استدعاء طريقة Evict () ، ستستدعي طريقة الالتزام () ضمنيًا طريقة Flush () أولاً. تتمثل وظيفة Flush في مسح ذاكرة التخزين المؤقت ، أي إدراج الكائن في الجلسة-> الإدراج مجموعة مؤقتة في قاعدة البيانات ، لكننا أطلقنا على طريقة Flush () قبل (ملاحظة: بعد استدعاء هذه الطريقة ، سيتم مسح المجموعة المؤقتة) ، وبالتالي فإن المجموعة المؤقتة لا تحتوي على كائنات على الإطلاق ، وبالتالي لن يتم إصدار بيان الإدراج. لن يقوم بتحديث حالة existsindatabase في persistenceContext. إرسال بنجاح.
دعونا نفكر في استخدام طريقة Evict () في استراتيجية توليد المفاتيح الأساسية الأصلية:
/ ***اختبار استراتيجية توليد المفتاح الأساسي الأصلي*/ public void testSave5 () {/*SENTEM SETATE والأشياء*/ جلسة الجلسة = NULL ؛ معاملة المعاملة = فارغة ؛ حاول { /*الحصول على الجلسة والأشياء* / الجلسة = hibernateutils.getSession () ؛ المعاملة = session.begintransaction () ؛ /*إنشاء مستخدم*/ user1 user = جديد user1 () ؛ user.setUname ("ma ying-jeou") ؛ user.setbirthday (date ()) ؛ / *** نظرًا لأن استراتيجية توليد المفاتيح الأساسية لـ USER1 هي أصلية ، بعد الاتصال Session.Save () ، سيتم تنفيذ عبارة INSERT ،* إرجاع المعرف الذي تم إنشاؤه بواسطة قاعدة البيانات ، المدرجة في إدارة الجلسة ، وتعديل حالة الوجود في الجلسة إلى SEAT ، ومسح المجموعة المؤقتة* إذا تم تعيين مستوى العزلة في قاعدة البيانات على عدم تقديمها ، ثم يمكننا رؤية البيانات الموفرة*. /* إخلاء كائن المستخدم من الجلسة ، أي ، تم طرده من خاصية EntityentRies الخاصة بـ persistencecontext*/ session.vict (المستخدم) ؛ / *** يمكن إرسالها بنجاح لأن السبات في مجموعة إدخال الجلسة عند تنظيف ذاكرة التخزين المؤقت* لا يمكن العثور على كائن المستخدم ، لذلك لن يتم إصدار بيان الإدراج ، ولن يتم تحديث حالة arexistindatabase في الجلسة*/ Transaction.Commit () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Transaction.Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }} من خلال تصحيح الأخطاء:
1. نظرًا لأن استراتيجية توليد المفاتيح الأساسية هي أصلية ، بعد استدعاء طريقة الحفظ ، سيتم إصدار عبارة إدراج على الفور ، وإعادة المعرف الذي تم إنشاؤه بواسطة قاعدة البيانات ، ودمج الكائن في إدارة الجلسة ، وتعديل خاصية الوجود في المجموعة المؤقتة إلى True ، أي ، هناك بيانات مقابلة في قاعدة البيانات ، والكائن في المجموعة المؤقتة. ومع ذلك ، نظرًا لمستوى عزل MySQL ، لا يمكننا رؤية البيانات قبل ارتكابها.
2. بعد استدعاء الحفظ ، يتم استدعاء الكائن ويتم طرد الكائن من الجلسة ، أي أنه يتم طرده من الكيانات في persistencecontext.
3. بعد استدعاء طريقة Evict () ، يمكن استدعاء طريقة الالتزام () بنجاح. يمكن حفظ الالتزام بنجاح ، لأنه قبل استدعاء Commice () ، سيتم تسمية طريقة Flush () ضمنيًا ، أي تنظيف ذاكرة التخزين المؤقت والبحث عن كائنات في المجموعة المؤقتة لإدراجها في قاعدة البيانات. ومع ذلك ، ستجد أنه لا توجد بيانات في المجموعة المؤقتة ، وبالتالي لن يتم إصدار بيان إدراج ، ولن يتم تحديث خاصية الوجود في برنامج PersistenceContext.
من خلال الحالات المذكورة أعلاه ، يمكننا أن نرى أنه في بعض الأحيان نحتاج إلى استدعاء طريقة Flush () لتنظيف ذاكرة التخزين المؤقت. بالإضافة إلى ذلك ، وجدنا أيضًا مشكلة من ما سبق ، أي عندما نحفظ () البيانات ، لا يمكننا رؤية البيانات قبل إرسالها ، أي أن مستوى عزل قاعدة البيانات محدود. الآن دعنا نتحدث عن مستوى عزل MySQL:
1. تحقق من مستوى العزلة الحالي لقاعدة بيانات MySQL:
حدد tx_isolation ؛
ملاحظة: من الشكل ، يمكننا أن نرى أن مستوى العزلة الافتراضي لقاعدة بيانات MySQL قابلة للتكرار ، مما يعني أنه لن تكون هناك قراءة غير قابلة للتكرار ، أي يجب تقديمها قبل قراءتها.
2. قم بتعديل مستوى العزلة الحالي لـ MySQL (على افتراض أنه لم يتم تقديمه للقراءة ، أي يمكن قراءته دون الالتزام):
set transaction isolation level read uncommited;
ما ورد أعلاه هو كل التفسير التفصيلي لرمز مستوى السلبات والرمز مستوى العزلة. آمل أن يكون ذلك مفيدًا للجميع. يمكن للأصدقاء المهتمين الاستمرار في الرجوع إلى الموضوعات الأخرى ذات الصلة على هذا الموقع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها. شكرا لك يا أصدقائك لدعمكم لهذا الموقع!