يتم تخزين ذاكرة التخزين المؤقت للجلسة مع الرسوم البيانية للكائنات المترابطة. افتراضيًا ، عندما تقوم Hibernate بتحميل كائنات العميل من قاعدة البيانات ، يتم تحميل جميع كائنات الطلب المرتبطة في نفس الوقت. أخذ فصول العميل والطلب كأمثلة ، افترض أن المفتاح الخارجي العميل في جدول الطلبات يسمح ليكون فارغًا
يتم استخدام طريقة Session的find() التالية لاسترداد جميع كائنات العميل في قاعدة البيانات:
List customerLists=session.find("from Customer as c");
عند تشغيل طريقة find() أعلاه ، ستقوم Hibernate أولاً بالاستعلام عن جميع السجلات في جدول العملاء ، ثم الاستعلام عن جدول الطلبات مع علاقات مرجعية بناءً على معرف كل سجل. ستقوم السبات بتنفيذ عبارات الاختيار التالية بدورها:
حدد * من العملاء ؛
حدد * من الطلبات حيث customer_id = 1 ؛
حدد * من الطلبات حيث customer_id = 2 ؛
حدد * من الطلبات حيث customer_id = 3 ؛
حدد * من الطلبات حيث customer_id = 4 ؛
من خلال عبارات SELECT 5 أعلاه ، يقوم Hibernate أخيرًا بتحميل 4 كائنات عميل و 5 كائنات ترتيب ، وتشكيل رسم بياني كائن مرتبط في الذاكرة.
يستخدم Hibernate سياسة البحث الافتراضي الآن عند استرداد كائنات الطلب المرتبطة بالعميل. هناك عيوبان رئيسيان في استراتيجية البحث هذه:
(1) عدد عبارات التحديد كبيرة جدًا ، وسيؤثر الوصول المتكرر إلى قاعدة البيانات على أداء الاسترجاع. إذا كنت بحاجة إلى الاستعلام عن كائنات العملاء ، فيجب تنفيذ عبارة الاستعلام N+1. هذه هي مشكلة الاستعلام الكلاسيكية N+1. لا تستخدم استراتيجية البحث هذه وظيفة استعلام اتصال SQL. على سبيل المثال ، يمكن إكمال عبارات SELECT 5 أعلاه بالكامل بواسطة عبارة SELESS 1 التالية:
حدد * من العملاء الذين تركوا أوامر الانضمام الخارجي
على العملاء
تستخدم عبارة SELECT أعلاه وظيفة استعلام Join Join Left الخاصة بـ SQL ، والتي يمكنها الاستعلام عن جميع سجلات جدول العملاء وسجلات جدول الطلبات المطابقة في عبارة SELECT.
(2) في المواقف التي يحتاج فيها منطق التطبيق فقط إلى الوصول إلى كائنات العملاء ولكن لا تطلب الكائنات ، فإن كائنات التحميل غير ضرورية تمامًا. هذه الكائنات غير الضرورية تضيع الكثير من مساحة الذاكرة.
لحل المشكلات المذكورة أعلاه ، يوفر السبات استراتيجيتين للبحث الأخريين: استراتيجية البحث المتأخرة واستراتيجية بحث عاجلة للاتصال. يمكن أن تتجنب استراتيجية الاسترجاع المتأخرة التحميل الزائد للكائنات المرتبطة التي لا يحتاج التطبيق إلى الوصول إليها. تستفيد استراتيجية استرجاع الاتصال الخارجي الأيسر العاجل من وظيفة استعلام الاتصال الخارجي لـ SQL ويمكن أن تقلل من عدد عبارات التحديد.
يجب مراعاة مشكلات الأداء عند الوصول إلى قواعد البيانات. بعد تعيين العلاقة بين 1 إلى عدد ، ستحدث مشكلة N +1 الأسطورية في الاستعلام.
1) 1 للكثيرين ، في 1 مربع ، يمكن العثور على كائنات n ، ثم يجب إخراج المجموعة المرتبطة بكائنات n ، لذلك يصبح استعلام SQL الأصلي n +1
2) كثير إلى 1. إذا قمت بالاستعلام عن كائنات M في أطراف متعددة ، فسيتم إخراج كائن أحزاب واحد المقابل لكائنات M ، وسيصبح أيضًا M+1.
1) كسول = صحيح ، لقد تخلف Hibernate3 بالفعل إلى Lazy = true ؛ عندما كسول = صحيح ، لن يتم الاستعلام عن الكائن المرتبط على الفور. لن يحدث إجراء الاستعلام إلا عندما يكون الكائن المرتبط (بالوصول إلى سماته ، الحقول غير المعيارية).
2) المستوى 2 ذاكرة التخزين المؤقت. عندما يكون الكائن أقل تحديثًا وحذفه وإضافته من الاستعلامات ، فلن يخاف تطبيق ذاكرة التخزين المؤقت من المستوى 2 من مشاكل N +1 ، لأنه حتى لو كان الاستعلام الأول بطيئًا ، فإن ذاكرة التخزين المؤقت ستكون سريعة جدًا بعد ذلك.
حلول مختلفة وأفكار مختلفة ، ولكن الحلقة الثانية تحدث فقط لاستخدام N +1 مرة أخرى.
3) بالطبع يمكنك أيضًا تعيين fetch=join(annotation : @ManyToOne() @Fetch(FetchMode.JOIN))
ما ورد أعلاه هو كل شيء عن المناقشة الموجزة لهذه المقالة حول قضية السبات N+1 ، وآمل أن تكون مفيدة للجميع. يمكن للأصدقاء المهتمين الاستمرار في الرجوع إلى الموضوعات الأخرى ذات الصلة على هذا الموقع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها. شكرا لك يا أصدقائك لدعمكم لهذا الموقع!