1. استعلام كائن الكيان
استعلام كائن الكيان هو أساس استعلام HQL. كلغة استفسار الكائن ، فإنها تختلف عن SQL أثناء عمليات الاستعلام. يجب استبدال المحتوى في سلسلة الاستعلام باسم الفصل واسم سمة الفصل. طريقة الاستعلام هذه بسيطة نسبيا. طالما أن لديك مهارات SQL ، فمن السهل جدًا استخدام HQL. ومع ذلك ، هناك بعض المشكلات التي يجب الانتباه إليها ، أي أن الاستعلام عن البيانات والحصول عليها ليس هو الغرض ، وما يجب مراعاته هو كيفية كتابة بيانات الاستعلام الفعالة ، وهو محور المناقشة.
1.N+1 مشكلة
(1) ما هي مشكلة N+1
عندما سمعت هذا الاسم لأول مرة ، قد يكون لدي شكوك. لم أسمع أبدًا عن مشكلة N+1 من قبل. إذن ماذا يعني؟ يشير N+1 إلى بيانات N في جدول ، لذلك عند الحصول على بيانات N ، سيتم إنشاء أمر N+1 SQL. وتسمى هذه العملية n+1. هنا ، يشير 1 إلى إصدار بيان يبحث عن قائمة الهوية ، ويشير N إلى إصدار بيانات N SQL بناءً على معرف لتحميل الكائنات ذات الصلة. هذا النوع من عمليات الاستعلام غير فعال للغاية وغالبًا ما يتم إنشاؤه في التكرار. وهذا يعني ، إذا قامنا بتحويل نتائج الاستعلام مباشرة إلى أعضاء تكرار ، فستحدث هذه المشكلة ، على النحو التالي:
public void testquery () {جلسة الجلسة = null ؛ جرب {session = hibernateutils.getSession () ؛ Session.begintransaction () ؛ /*** ستكون هناك مشكلة N+1. ما يسمى بـ N+1 يستحق إصدار بيانات N+1 SQL** 1: إصدار عبارة تعلق قائمة المعرف** n: إصدار بيانات n sql استنادًا إلى المعرف وتحميل الكائن ذي الصلة*/ iterator iter = session.createquery ("من الطالب"). بينما (iter.hasnext ()) {student student = (student) iter.next () ؛ system.out.println (student.getName ()) ؛ } session.getTransaction (). commice () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Session.getTransaction (). Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }}سوف يتسبب رمز الاستعلام أعلاه في مشكلة N+1 ، لأنه يتم إرجاع الاستعلام كمؤشر ، بحيث يتم إصدار عبارة SQL إذا لم يتم إنشاؤها مرة واحدة. يعتمد هذا بشكل أساسي على آلية استعلام التكرار ، والتي تتصرف البيانات من ذاكرة التخزين المؤقت. إذا لم تكن البيانات موجودة في ذاكرة التخزين المؤقت ، فسيتم تحويل البيانات إلى ذاكرة أولاً ، لذلك سيتم إصدار بيان استعلام SQL في هذا الوقت ، لذلك سيتم إنشاء عبارة SQL كل تكرار. طريقة الكتابة هذه هي في الواقع خطأ ويمكن حلها باستخدام طرق أخرى لتحسينها.
(2) تجنب مشكلة n+1
تحدث مشكلة N+1 بسبب الاستخدام غير السليم للتكرار. بالطبع ، يمكن استخدام طرق أخرى لتجنب مشكلة N+1. هنا طريقة قائمة. الفرق الأكبر بين القائمة والتكرار هو أن القائمة تضع البيانات في ذاكرة التخزين المؤقت ، ولكنها لا تستخدم ذاكرة التخزين المؤقت. بشكل افتراضي ، ستصدر القائمة عبارات SQL في كل مرة. قبل استخدام التكرار ، يمكنك استخدام قائمة لحفظ البيانات في قاعدة البيانات ، بحيث يمكن للتكرار القراءة من ذاكرة التخزين المؤقت عند الوصول إلى البيانات ، وتجنب حدوث مشكلات N+1. الرمز كما يلي:
public void testquery () {جلسة الجلسة = null ؛ جرب {session = hibernateutils.getSession () ؛ Session.begintransaction () ؛ قائمة الطلاب = session.createquery ("من الطالب"). list () ؛ System.out.println ("---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- بعد ذلك ، لا يتم إصدار أي عبارات SQL بناءً على المعرف ، ويتم استخدام البيانات الموجودة في ذاكرة التخزين المؤقت مباشرة * * طريقة التكرار في حالة وجود بيانات في ذاكرة التخزين المؤقت ، وإلا ستحدث مشكلات N+1 */// يمكنك استخدام الطالب as is iter = () System.out.println (studentName ()) ؛ }}يتجنب المثال أعلاه مشكلة N+1 ، لأنه بعد إجراء عملية القائمة ، سيتم وضع البيانات في ذاكرة التخزين المؤقت للجلسة (ذاكرة التخزين المؤقت للمستوى الأول). لذلك ، عند استخدام التكرار ، سيتم إصدار بيان للاستعلام عن قائمة المعرف ، ثم سيتم تحميل البيانات المقابلة في ذاكرة التخزين المؤقت وفقًا للمعرف. إذا كان هناك بيانات مطابقة لها في ذاكرة التخزين المؤقت ، فلن يتم إصدار استعلام بيان SQL بناءً على المعرف ، وسيتم استخدام البيانات الموجودة في ذاكرة التخزين المؤقت مباشرة. يمكن أن تؤدي طريقة التكرار إلى تحسين الأداء إذا كانت البيانات موجودة في ذاكرة التخزين المؤقت ، وإلا ستحدث مشاكل N+1.
2. استعلام التنقل الكائن
يشير التنقل في الكائن إلى الحصول على البيانات من كائن آخر وفقًا لتنقل سمة الكائن في كائن واحد. هذا يمكن أن يبسط عبارات الاستعلام وتحسين أساليب الاستعلام. إذا اتبعنا أفكارنا المعتادة ، فيجوز لنا إعادة كتابة وكتابة كائن من فئة أخرى للحصول على تشغيل كائن آخر ، وهو أكثر تعقيدًا لمقارنة بيان التنقل في الكائن.
suppressWarnings ({"Unchecked" ، "RawTypes"}) public void testquery1 () {session session = null ؛ جرب {session = hibernateutils.getSession () ؛ Session.begintransaction () ؛ // إرجاع قائمة سمة SET SET ، ونوع العنصر وأنواع السمات في فئة الكيان هي نفس القائمة الطلاب = SATES.CREATEQUERY ("من الطالب S s.classes.name مثل" ٪ 2 ٪ '"). list () ؛ لـ (iterator item = students.iterator () ؛ ite.hasnext () ؛) {student obj = (student) ite.next () ؛ system.out.println (obj.getName ()) ؛ } session.getTransaction (). commice () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Session.getTransaction (). Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }}يستخدم عبارة الاستعلام في المثال أعلاه طريقة التنقل في الكائن. بيان الاستعلام هو استعلام المعلومات من كائن الطالب ، لكن سمات الكائن المراد مقارنتها تأتي من سمة اسم كائن الفئات. في هذا الوقت ، سيؤدي استخدام طريقة استعلام التنقل الكائن إلى تحسين كفاءة الاستعلام بشكل كبير وتحسين عبارة الاستعلام. إذا كانت طريقة استعلام عادية ، فقد يتم إنشاء عدد كبير من عبارات الاتصال ، وهو أمر معقد للغاية.
2. استعلام SQL الأصلي
تتمثل قيمة الاستعلام الأصلية في استخدام عبارات SQL للاستعلام والحصول على البيانات ، بدلاً من استخدام عبارات HQL. طريقة الاستخدام الخاصة بها هي في الواقع بسيطة للغاية ، على غرار HQL. تحتاج فقط إلى استخدام CreateSqLquery طريقة للاستعلام. إنه يشبه في الواقع طريقة مبكر HQL. الرمز كما يلي:
public void testqeury () {جلسة الجلسة = null ؛ جرب {session = hibernateutils.getSession () ؛ Session.begintransaction () ؛ قائمة قائمة = session.createsqlquery ("حدد * من t_student"). list () ؛ لـ (iterator item = list.iterator () ؛ ite.hasnext () ؛) {object [] obj = (object []) ite.next () ؛ system.out.println (obj [0]+"،"+obj [1]) ؛ } session.getTransaction (). commice () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Session.getTransaction (). Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }}يستخدم الرمز أعلاه طريقة CreateSqLquery. سلسلة الاستعلام في الطريقة هي عبارة SQL. إنه ينفذ طريقة الاستعلام الأساسية للسلسلة. الفرق هو أن HQL لديه طبقة أخرى من العبوة ، وتكوين خيارات اللهجة المقابلة في hibernate.cfg.xml لإكمال التعيين.
3. استعلام الاتصال
غالبًا ما يتم استخدام استعلامات الاتصال في SQL للحصول على مجموعة من الكائنات المتعددة. من بينها ، الأكثر شيوعًا هو الانضمام الداخلي ، والانضمام الأيسر ، والانضمام الأيمن ، وما إلى ذلك ، والتي تشير إلى استعلام Join Inner ، والاستعلام اليساري Join Join ، واستعلام Join Join. المحتوى الذي يعودونه أثناء الاستعلام هو المنتج الديكارت بين الكيانات ، ومحتوى الاستعلام وبعض محتوى الجدول الأيسر ، ومحتوى الاستعلام وبعض محتوى الجدول الأيمن ، ووظيفة الاستعلام قوية. طريقة استعلام الاتصال لـ HQL والاستعلام عن اتصال SQL هي نفسها في نتائج الاستعلام ، ولكن هناك اختلافات طفيفة في عبارات الاستعلام.
1. الاتصال الداخلي
يمكن الاستعلام عن الاستعلام داخل HQL باستخدام بيان الانضمام الداخلي أو بيان الانضمام ، وبيان النتائج الذي تم الحصول عليه هو منتج ديكارت. على غرار استعلام SQL Intra-Connection ، يتم تقسيم استعلام Join's Join إلى نوعين: صريح وضمن. يشير الاستعلام المعروض إلى الكلمة الرئيسية Join في سلسلة الاستعلام. الاستعلام الضمني لا يحتاج إلى إضافة انضمام في السلسلة.
// اتصال داخلي suppressWarnings ({"Unchecked" ، "RawTypes"}) public void testquery () {session session = null ؛ جرب {session = hibernateutils.getSession () ؛ Session.begintransaction () ؛ // إرجاع قائمة سمة تعيين النتائج ، فإن نوع العنصر وأنواع السمات في فئة الكيان هي نفس القائمة الطلاب = Session.Createquery ("Select S.Name ، C.Name from student s join S S.Classes C"). list () ؛ لـ (iterator item = students.iterator () ؛ ite.hasnext () ؛) {object [] obj = (object []) ite.next () ؛ System.out.println (OBJ [0]) ؛ } session.getTransaction (). commice () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Session.getTransaction (). Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }}
2. الاتصال الخارجي
يتم تقسيم الاتصالات الخارجية إلى اتصال خارجي الأيسر والاستعلام عن الاتصال الخارجي الأيمن. طرق الاستعلام متشابهة ، ولكن نتيجة الاستعلام مختلفة. هم نفس الاتصال الخارجي لـ SQL في نتائج الاستعلام. الفرق هو طريقة الكتابة. الرمز المحدد كما يلي:
suppresswarnings ({"unchecked" ، "RawTypes"}) public void testquery () {session session = null ؛ جرب {session = hibernateutils.getSession () ؛ Session.begintransaction () ؛ // إرجاع قائمة سمة تعيين النتائج ، فإن نوع العنصر وأنواع السمات في فئة الكيان هي نفس القائمة الطلاب = Session.Createquery ("SELECT S.Name ، C.Name من student s left join s.classes c"). list () ؛ لـ (iterator item = students.iterator () ؛ ite.hasnext () ؛) {object [] obj = (object []) ite.next () ؛ System.out.println (OBJ [0]) ؛ } session.getTransaction (). commice () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Session.getTransaction (). Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }}يستخدم الرمز أعلاه عبارة استعلام خارجي الأيسر. تشبه طريقة الاستعلام اليمنى الخارجي اليمنى الانضمام الخارجي الأيسر. فقط تحويل اليسار إلى اليمين. يتم حفظ بيانات الاستعلام في كائن القائمة ، ويمكن الحصول على محتوى الاستعلام من خلال القائمة.
4. استعلام تسمية خارجي
يشير الاستعلام الخارجي المسماة إلى كتابة عبارات الاستعلام في ملف رسم الخرائط واستخدام علامة <Query> لتحديد عبارات HQL في ملف التعيين. وبهذه الطريقة ، يمكن أن تدرك عبارات HQL المحددة وظيفة تكوين الوظيفة. إذا كانت هناك مشكلة ، فقط بحاجة إلى تعديل التكوين. إذا كنت ترغب في استخدام عبارة SQL هذه ، فيمكنك استخدام طريقة Session.getNamedQuery () في البرنامج للحصول على سلسلة استعلام HQL ، كما هو موضح في المثال التالي.
1. بيان الاستعلام الخارجي
يوضح المثال التالي تطبيق عبارات الاستعلام الخارجي ، وأضف علامة <Query> إلى ملف التعيين ، وإضافة سمة الاسم إلى العلامة ، وأضف السلسلة إلى <!
<؟ table = "t_student"> <id name = "id"> <generator // id> <property name = "name"/> <property name = "createTime"> </splyment> <!-أضف عمودًا جديدًا إلى الطالب على جانب واحد ، ويجب أن يكون اسم العمود هو نفس الفصول الدراسية> <s-to- <query name = "querystudent"> <! ]]> </query> </hibernate mapping>
يضع الاستعلام الخارجي المسمى عبارة الاستعلام في ملف التعيين ، بحيث يمكن اعتباره سلسلة استعلام عامة. هذه هي مصلحتها ، بحيث يمكن الحصول على ملفات البرامج الأخرى واستخدامها. بالإضافة إلى ذلك ، فإنه يزيد من راحة التعديل كسلسلة عامة.
2. تطبيق البرنامج
بعد تحديد بيانات الاستعلام الخارجية ، من الضروري استخدامها في البرنامج. يوفر HQL طريقة getNameQuery للحصول على سلسلة بيان الاستعلام الخارجية. يجب إضافة اسم المؤشر الخارجي إلى هذه الطريقة. سوف يستفسر HQL عن كتلة عبارة SQL المقابلة بناءً على اسم المؤشر ، على النحو التالي:
// استعلام تسمية خارجي suppressWarnings ({"uncheced" ، "RawTypes"}) public void testquery () {session session = null ؛ جرب {session = hibernateutils.getSession () ؛ Session.begintransaction () ؛ قائمة الطلاب = session.getNamedQuery ("QueryStudent"). setParameter (0 ، 10) .List () ؛ لـ (iterator item = students.ite.hasnext () ؛) {student obj = (student) ite.next () ؛ system.out.println (obj.getName ()) ؛ } session.getTransaction (). commice () ؛ } catch (استثناء e) {E.PrintStackTrace () ؛ Session.getTransaction (). Rollback () ؛ } أخيرًا {hibernateUtils.Closedessesse (الجلسة) ؛ }}