تصف هذه المقالة طريقة تشغيل الدُفعات. شاركه للرجوع إليه ، على النحو التالي:
معالجة الدُفعات السباتية
تدير Hibernate قاعدة البيانات تمامًا بطريقة موجهة نحو الكائن. عندما يتم تشغيل كائن ثابت بطريقة موجهة نحو الكائن في البرنامج ، سيتم تحويله تلقائيًا إلى عملية على قاعدة البيانات. على سبيل المثال ، عند استدعاء طريقة DELETE () لحذف كائن ثابت ، ستكون السبات مسؤولة عن حذف سجلات البيانات المقابلة ؛ عند تنفيذ طريقة SET للكائن المستمر ، سيتم تحويل Hibernate تلقائيًا إلى طريقة التحديث المقابلة وتعديل السجلات المقابلة لقاعدة البيانات.
والسؤال هو ما إذا كان هناك حاجة إلى تحديث 100000 سجل في نفس الوقت ، هل تحتاج إلى تحميل 100000 سجل واحد تلو الآخر ، ثم استدعاء طريقة المجموعة بدورها - هذا ليس فقط مرهقة ، ولكن أيضًا أداء الوصول إلى البيانات أمر سيء للغاية. لسيناريو معالجة الدُفعات هذا ، يوفر Hibernate حل معالجة الدُفعات. يقدم ما يلي كيفية مواجهة وضع معالجة الدُفعات هذا من ثلاثة جوانب: إدخال الدُفعات ، وتحديث الدُفعات وحذف الدُفعات.
1 دفعة إدراج
إذا كنت بحاجة إلى إدراج 100000 سجل في قاعدة البيانات ، فقد تستخدم السبات عادة ما يلي:
جلسة الجلسة = SessionFactory.OpenSession () ؛ المعاملات tx = session.begintransaction () ؛ لـ (int i = 0 ؛ i <100000 ؛ i ++) {user u = new user (......) ؛ Session.save (customer) ؛} tx.commit () ؛ session.close () ؛ولكن مع تشغيل هذا البرنامج ، سيفشل دائمًا في مرحلة ما ويتم إلقاء OutofMemoryException. وذلك لأن جلسة Hibernate تحمل ذاكرة التخزين المؤقت من المستوى 1 المطلوب ، وسيتم تخزين جميع مثيلات المستخدم في منطقة ذاكرة التخزين المؤقت على مستوى الجلسة.
لحل هذه المشكلة ، هناك فكرة بسيطة للغاية: تحديث البيانات التي تم تخزينها بواسطة الجلسة بانتظام في قاعدة البيانات ، بدلاً من ذاكرة التخزين المؤقت لها دائمًا على مستوى الجلسة. يمكنك التفكير في تصميم تراكم ، والذي يزداد بمقدار 1 لكل مثيل مستخدم يتم حفظه. حدد ما إذا كانت البيانات الموجودة في ذاكرة التخزين المؤقت للجلسة تحتاج إلى مسح في قاعدة البيانات بناءً على قيمة التراكم.
فيما يلي مقتطف من التعليمات البرمجية التي تضيف 100000 حالة مستخدم:
private void testuser () يلقي استثناء {// جلسة الجلسة المفتوحة = hibernateutil.currentsession () ؛ // ابدأ معاملة المعاملة tx = session.begintransaction () ؛ // loop 100 000 مرة وأدخل 100 000 سجل لـ (int i = 0 ؛ i <1000000 ؛ i ++) {// إنشاء مستخدم مستخدم uster u1 = new user () ؛ u1.setName ("xxxxx" + i) ؛ u1.setage (i) ؛ u1.setnationality ("الصين") ؛ // Cach The User مثيل المستخدم Session.save (u1) ؛ // عندما يكون المتراكم مضاعفًا 20 ، قم بتدفق البيانات في الجلسة في قاعدة البيانات وقم بمسح ذاكرة التخزين المؤقت للجلسة إذا (i ٪ 20 == 0) {session.flush () ؛ session.clear () ؛ tx.Commit () ؛ tx = session.begintransaction () ؛ }} // CANKE TX.COMMIT () ؛ // إغلاق معاملة heibernateutil.closesession () ؛}في الرمز أعلاه ، عندما تكون I ٪ 20 == 0 ، تتم كتابة البيانات المخزنة مؤقتًا في الجلسة يدويًا إلى قاعدة البيانات ويتم تقديم المعاملة يدويًا. إذا لم يتم تقديم المعاملة ، فسيظل البيانات مخزنة مؤقتًا في مكتب المعاملات - لم تدخل قاعدة البيانات ، مما سيؤدي أيضًا إلى استثناء من تدفق الذاكرة.
هذا هو معالجة ذاكرة التخزين المؤقت على مستوى الجلسة ، ويجب إيقاف تشغيل ذاكرة التخزين المؤقت الثانوية لـ SessionFactory من خلال التكوين التالي.
hibernate.cache.use_second_level_cache false
ملاحظة: بالإضافة إلى مسح ذاكرة التخزين المؤقت على مستوى الجلسة يدويًا ، من الأفضل إيقاف تشغيل ذاكرة التخزين المؤقت الثانوية على مستوى الجلسة. خلاف ذلك ، حتى إذا تم مسح ذاكرة التخزين المؤقت على مستوى الجلسة يدويًا ، فقد يتم طرح استثناء لأنه لا يزال هناك ذاكرة التخزين المؤقت على مستوى SessionFactory.
2 تحديثات الدُفعات
الطريقة الموضحة أعلاه مناسبة أيضًا لبيانات تحديث الدُفعات. إذا كنت بحاجة إلى إرجاع صفوف متعددة من البيانات ، فيمكنك استخدام طريقة SCROLL () للاستفادة الكاملة من مزايا الأداء التي تقدمها المؤشرات من جانب الخادم. فيما يلي مقتطف رمز لتحديثات الدُفعات:
private void testuser () يلقي استثناء {// جلسة الجلسة المفتوحة = hibernateutil.currentsession () ؛ // ابدأ معاملة المعاملة tx = session.begintransaction () ؛ // استعلام جميع السجلات في جدول المستخدم scrollableresults مستخدمي = session.createquery ("من المستخدم") .setCacheMode (cachemode.ignore) .scroll (scrollmode.forward_only) ؛ عدد int = 0 ؛ // المعاملة جميع السجلات في جدول المستخدم بينما (user.next ()) {user u = (user) users.get (0) ؛ U.SetName ("اسم المستخدم الجديد" + العد) ؛ // عندما يكون العد مضاعفًا من 20 ، قم بتدفق النتيجة المحدثة من الجلسة إلى قاعدة البيانات إذا (++ count ٪ 20 == 0) {session.flush () ؛ session.clear () ؛ }} tx.commit () ؛ hibernateutil.closesession () ؛} وبهذه الطريقة ، على الرغم من أنه يمكن إجراء تحديثات الدُفعات ، إلا أن التأثير ضعيف للغاية. كفاءة التنفيذ ليست عالية ، ويكون استعلام البيانات مطلوبًا أولاً ، ثم يتم تنفيذ تحديث البيانات. سيكون هذا التحديث بمثابة تحديث لكل خط ، أي في كل مرة يتم تحديث صف من السجلات ، يجب تنفيذ عبارة تحديث ، والأداء منخفض للغاية.
لتجنب ذلك ، يوفر Hibernate بناء جملة HQL مماثلة لـ SQL لتحديثات الدُفعات وحذف الدُفعات.
3 تحديث/حذف على طراز SQL
تدعم عبارات HQL التي توفرها Hibernate أيضًا تحديث الدُفعات وحذف بناء الجملة.
إن تنسيق بناء الجملة لتحديث الدُفعات وحذفه هو كما يلي:
تحديث | حذف من؟ className [حيث where_conditions]
هناك أربع نقاط جديرة بالملاحظة حول تنسيق بناء الجملة أعلاه:
● في البند من ، من الكلمة الرئيسية اختيارية. أي أنه لا يمكنك الكتابة من الكلمات الرئيسية على الإطلاق.
● لا يمكن أن يكون هناك اسم فئة واحد فقط في البند ، ولا يمكن أن يكون اسم الفصل اسم مستعار.
● لا يمكنك استخدام الاتصالات في عبارات HQL الدُفعات ، لا صريحة أو ضمنية. ولكن يمكن استخدام الفائزين الفرعيين في الفقرة حيث.
● البند بالكامل حيث يكون الاختياري.
على افتراض أنك تحتاج إلى تغيير سمة الاسم لمثيل فئة المستخدم ، يمكنك استخدام مقتطف الرمز التالي:
private void testuser () يلقي استثناء {// جلسة الجلسة المفتوحة = hibernateutil.currentsession () ؛ // ابدأ معاملة المعاملة tx = session.begintransaction () ؛ // تحديد BATCH UPDATE HQL STRING HQLUPDATE = "Update User Set Name =: NewName" ؛ . // ارتكاب معاملة tx.commit () ؛ hibernateutil.closesession () ؛}كما يتضح من الكود أعلاه ، فإن هذا الجملة يشبه إلى حد كبير بناء جملة executeupdate من المعدة. في الواقع ، فإن هذا التحديث الدُحمي لـ HQL يعترض مباشرة من عبارة تحديث بناء جملة SQL.
ملاحظة: عند استخدام بناء جملة تحديث الدُفعات هذا ، عادة ما تحتاج فقط إلى تنفيذ عبارة تحديث SQL مرة واحدة لإكمال جميع التحديثات التي تلبي السجلات الشرطية. ولكن قد يكون من الضروري أيضًا تنفيذ عبارات تحديث متعددة ، لأن هناك حالات خاصة مثل تعيين الميراث ، مثل وجود مثيل للشخص ، والذي يحتوي على مثيل فئة فرعية للعميل. عندما يقوم الدُفعات بتحديث مثيلات الشخص ، يجب أيضًا تحديث مثيل العميل. إذا كنت تستخدم إستراتيجية رسم خرائط Loined-Subclass أو Union-Subclass ، يتم حفظ مثيلات الشخص والعميل في جداول مختلفة ، لذلك قد تكون هناك حاجة إلى عبارات تحديث متعددة.
قم بتنفيذ حذف HQL ، واستخدم طريقة Query.executeUpdate (). فيما يلي مقتطف رمز يحذف جميع السجلات أعلاه في وقت واحد:
private void testuser () يلقي استثناء {// جلسة جلسة جلسة مفتوحة = hibernateutil.currentsession () ؛ // ابدأ معاملة المعاملة tx = session.begintransaction () ؛ // تحديد Batch Deletion HQL string String HQLuPdate = "Delete user" ؛ . // ارتكاب معاملة tx.commit () ؛ // إغلاق جلسة heibernateutil.closesession () ؛}إرجاع قيمة عدد صحيح بواسطة Query.executeupdate () ، والتي هي عدد السجلات المتأثرة بهذه العملية. في الواقع ، تتم عمليات السبات الأساسية من خلال JDBC. لذلك ، إذا كانت هناك مجموعات من عمليات التحديث أو الحذف التي يتم تحويلها إلى عبارات تحديث أو حذف متعددة ، فإن الطريقة تُرجع عدد السجلات المتأثرة ببيان SQL الأخير.
آمل أن يكون الوصف في هذه المقالة مفيدًا لبرمجة Java للجميع استنادًا إلى إطار السبات.