في المرة الأخيرة التي تعلمنا فيها كيفية استخدام المعايير لأداء العمليات ذات الصلة معًا ، ولكن نظرًا لأن المعايير ليست طريقة الاستعلام الموصى بها رسميًا من قبل السبات ، فإننا لا نستخدمها كثيرًا. الآن دعنا نلقي نظرة على HQL الموصى بها رسميًا وتعرّف على مدى قوتها معًا.
ما هو الفرق بين HQL ، أو بيان الاستعلام السباتي و SQL؟ الفرق بين رسالة واحدة ، هاها.
بالطبع هذا ليس هو الحال. يكمن الفرق بين HQL و SQL في الأفكار المختلفة. يستخدم HQL اتجاهًا موجهًا للكائن للاستعلام ، بينما يستخدم SQL استعلامًا لجداول قاعدة البيانات ثنائية الأبعاد. ما تم تضمينه هنا هو الفرق في الأفكار. HQL هو في الواقع SQL ، وهو مصنوع من السبات لتحويل وتوليد SQL داخليًا.
1) بدون مزيد من اللغط ، دعونا نلقي نظرة على قوته.
من المستخدم
هذا الرمز مألوف للغاية ، لأننا غالبًا ما نستخدم من أسماء الجدول في SQL ، ولكن الفرق هنا هو أن المستخدم ليس هو اسم الجدول هنا ، ولكن اسم فئة الكيان ، و Hibernate يساعدنا على تعيينها.
قم بربط عبارات SQL ، إذا أردنا العثور على سمة معينة والحد المشروط وفقًا لسمة معينة ، فيمكننا الحصول على بيان مماثل:
حدد usr.name ، usr.age من المستخدم حيث usr.age> 20 و usr.age <60
وبهذه الطريقة ، وجدنا أسماء وأعمار المستخدمين الذين تزيد أعمارهم عن 20 عامًا وأصغر من 60 عامًا. من السهل الفهم.
يمكن استخدام و ، أو ، مثل ، <،> ، = وما إلى ذلك في عبارات SQL في HQL.
تجدر الإشارة إلى أنه عندما نستفسر عن سمات متعددة ، فإن النتيجة التي تم إرجاعها هي كائن [] ، وعندما يتم إرجاع الكائن فقط. هذا يتطلب طرق تحليل مختلفة ، لذلك تحتاج إلى الانتباه إليها عند الاستعلام.
2) بالطبع ، قلنا في وقت سابق أن HQL موجهة نحو الكائن ، وإذا فعلنا ذلك ، فهي ليست فكرة موجهة نحو الكائن. دعونا نغيره:
حدد مستخدمًا جديدًا (usr.name ، usr.age) من usr usr حيث usr.age> 20وبهذه الطريقة ، وضعنا نتيجة الاستعلام في كائن المستخدم. لاحظ أن مُنشئ المستخدم يسمى هنا. يجب أن يكون هناك مُنشئ مستخدم يتلقى معلمتين في فئة المستخدم ، وإلا سيتم الإبلاغ عن خطأ. رسالة الخطأ تقريبًا على النحو التالي:
غير قادر على تحديد موقع مُنشئ مناسب على الفصل [org.hibernate.tutorial.domain8.user]
لا يمكن أن تجد مُنشئًا مناسبًا. من الواضح جدًا أنه فقط أضف المُنشئ الذي يتلقى المعلمات المقابلة.
لاحظ أنه عندما فحصنا المعرف المقابل ، لم نكتشف ذلك. إذا اتصلنا بالطريقة SaveorUpDate في هذا الوقت ، فقد أجرى بالفعل العملية المحفوظة.
لنلقي نظرة على رمز الاختبار:
بعد تنفيذ بيان الاستعلام أعلاه ، أقوم بإجراء العمليات التالية:
بينما (iter.hasnext ()) {user user = (user) iter.next () ؛ user.setName ("sun2") ؛ Session.SaveorUpDate (user) ؛ } في هذا الوقت ، بيان السبات هو:
Hibernate: insert في قيم المستخدم (user_name ، العمر) (؟ ،؟)
يدرج واحدة جديدة ، وليس تحديث.
ثم إذا احتجنا إلى التحديث ، نحتاج إلى معرفة المعرف معًا:
حدد مستخدمًا جديدًا (usr.name ، usr.age ، usr.id) من usr usr where usr.age> (حدد avg (usr.age) من usr)
تذكر تعديل مُنشئ المستخدم.
في هذا الوقت ، نقوم بتنفيذ رمز الاختبار الخاص بنا مرة أخرى وستحصل على:
Hibernate: تحديث المستخدم تعيين user_name =؟ ، العمر =؟ أين user_id =؟
حدد usr.name من المستخدم usr حيث usr.age> (حدد avg (usr.age) من usr)
يكتشف هذا HQL اسم المستخدم الأكبر من متوسط العمر.
4) في السبات 3 ، يمكننا بسهولة تحديث الكائنات وحذفها ، دون الحاجة إلى التحميل أولاً ثم حذفها في 2. يمكننا القيام بذلك مباشرة في بيان واحد:
تحديث اسم المستخدم name = '123123' حيث name = 'Sun33'
حذف العبارات متشابهة:
حذف المستخدم حيث الاسم = '123123'
5) من السهل أيضًا تجميعها وفرزها في السبات. ما عليك سوى استخدام المجموعة وترتيبها ، ولن أتحدث عنها أكثر في هذا الوقت.
6) نرى أن ما سبق مكتوب مباشرة للاستعلام أو التحديث. إذا كنا بحاجة إلى مهمة ديناميكية ، أو هناك الكثير من الواجبات ، لا يمكننا لصق سلاسل مثل JDBC. تشير التقديرات إلى أن هناك أكثر من 5 ، وكل شخص في فريق المشروع يريد أن يوبخني ، هاها.
من الأفضل استخدام طريقة حديثة ، واستخدام العناصر النائبة بدلاً من ذلك ، ثم تعيين قيم محددة.
رمزنا المباشر:
استعلام الاستعلام = session.createquery ("حدد مستخدمًا جديدًا (usr.name ، usr.age ، usr.id) من usr usr where usr.name =؟") ؛ Query.SetString (0 ، "Shun") ؛ نرى أن هذه الطريقة مشابهة لعملية الإعداد التي نستخدمها مباشرة. تم تعيينه من خلال المجموعة *** ، ولكن الفرق هو أن الموقف هنا يبدأ من 0 ، في حين يبدأ الإعداد من 1 ، لذلك إيلاء اهتمام خاص لها هنا.
هناك أيضًا طريقة للجلسة.
يسمى العنصر النائب الذي استخدمناه أعلاه العنصر النائب للطلب ، وهناك واحد آخر يسمى العنصر النائب المرجعي. لنلقي نظرة:
استعلام Query = Session.Createquery ("حدد مستخدمًا جديدًا (usr.name ، usr.age ، usr.id) من usr usr where usr.name =: name") ؛ Query.SetParameter ("name" ، "Shun") ؛ رأيت أن هناك شيئًا مثل: الاسم في بيان HQL الخاص بنا. هذا هو عنصر نائب مرجعي. نحتاج فقط إلى تعيين القيمة من خلال setParameter لاحقًا. لاحظ أن المعلمة الأولى هنا تحتاج إلى أن تتوافق مع قيمة العنصر النائب في عبارة HQL.
بالطبع ، قد يقول بعض الناس أن هذا ليس موجهًا نحو الكائن ، لذلك دعنا نذهب إلى الكائنات مرة أخرى:
أولاً ، قم بإنشاء فئة لتغليف القيمة التي نستفسر عنها
الفئة العامة userQuery {اسم السلسلة الخاصة ؛ عصر INT الخاص ؛ // حذف طريقة Get/SET QUERY QUERY = SATES.Createquery ("حدد مستخدمًا جديدًا (usr.name ، usr.age ، usr.id) من المستخدم usr حيث usr.name =: name") ؛ userQuery uq = new userQuery () ؛ UQ.SetName ("Shun") ؛ Query.SetProperties (UQ) ؛ نحن نغلف القيم التي نحتاجها للاستعلام مباشرة من خلال هذه الفئة. كائن جدا الموجهة نحو الكائن.
لدى بعض فرق المشروع بعض اللوائح الغريبة التي لا يُسمح لبيانات SQL بالظهور في الكود. إذا كانت هذه مواصفات ، فإن جميع رموز شركتنا التي رأيتها غير مؤهلة. الكثير من الربط بين الأوتار في الكأس يجعلها تبدو مكتئبًا. من الصعب حقًا أن تتأذى للحفاظ على المشاريع الحالية.
لا يُسمح ببيانات SQL في الكود. هذا اقتراح جيد ، لكنه يعتمد على هذه المناسبة. دعنا نلقي نظرة على كيفية تكوين السبات HQL في رسم الخرائط.
انظر مباشرة إلى ملف التكوين:
<query name = "querybyname"> <! [cdata [من المستخدم usr حيث usr.name =: name]]
أضفنا علامة كهذه ، مما يشير إلى أنه عبارة عن عبارة HQL.
عندما نحتاج إلى الحصول على هذا البيان ، نحتاج فقط إلى إضافة جملة إلى الكود:
Query Query = Session.getNamedQuery ("QueryByName") ؛ بهذه الطريقة ، يتم الحصول على بيان HQL.
يمكن أيضًا الاستعلام عن HQL باستخدام مجموعات في SQL ، مثل Joinn Inner ، اليسار الخارجي اليسار ، والانضمام الخارجي الأيمن ، والانضمام الكامل.
دعونا نلقي نظرة على استخدامهم:
دعونا نلقي نظرة على فئة الكيان أولاً ، ما نحتاج إلى استخدامه في اختباراتنا:
الطبقة العامة tuser تنفذ مسلسل {private static final long serialversionuid = 1l ؛ معرف int الخاص ؛ عصر INT الخاص ؛ اسم السلسلة الخاصة ؛ مجموعة خاصة <address> عناوين = new Hashset <Dehadt> () ؛ . معرف int الخاص ؛ عنوان السلسلة الخاص ؛ مستخدم Tuser الخاص ؛ // حذف GET/SET METLEST} لنلقي نظرة على ملف التعيين:
<hibernate-mapping package = "org.hibernate.tutorial.domain6"> <class name = "tuser" table = "t_user" dynamic-insert = "true" dynamic-update = "true"> <id name = "id" column = "id"> name = "Age" type = "java.lang.integer" column = "Age"/> <set name = "address" cascade = "all" table = "t_address" ververse = "true" package = "org.hibernate.tutorial.domain6"> <class name = "address" table = "t_address" dynamic-insert = "false" dynamic-update = "false" dynamic-update = "false" "dynamic-update =" id "type =" java.lang.integer "> type = "java.lang.string"/> <to to one name = "user" column = "user_id" not-null = "true"> </to to one> </class> </ hibernate mapping>
تحتاج فقط إلى تعديل اسم الحزمة المقابلة.
دعونا نجري اختبارات رسمية:
قبل الاختبار ، دعونا نلقي نظرة على البيانات في الجدول:
بيانات جدول T_Address هي كما يلي:
بيانات جدول T_USER هي كما يلي:
1) أولاً ، دعنا نلقي نظرة على الوصلة الداخلية ، التي تم جلبها في HQL بواسطة Inner Join Fetch. لاحظ أن معنى الجلب هنا هو جلب البيانات المطلوبة. إذا لم يتم استخدام جلب ، فإن البيانات التي جلبناها هي من نوع البيانات [].
لنلقي نظرة أولاً
من Tuser usr Inner Join
عندما نديرها ، نرى أن إخراج السبات هو:
hibernate: حدد tuser0_.id as id1_0_ ، addresses1_.id as id0_1_ ، tuser0_.name as name1_0_ ، tuser0_.age Age1_0_ ، addresses1_.address as address0_1_ ، addresses1_.user_id as user3_0_1_ ، T_Address addresses1_ on tuser0_.id = addresses1_.user_id
يمكننا أن نرى النتائج عند الجري في MySQL:
يمكننا أن نرى أن السبات يحوله إلى بيان انضمام داخلي ويكتشف العنوان.
نرى أنه لا يوجد سجل لـ SHUN4 في النتيجة ، لأنه ليس لديه العنوان والسجل المقابلان.
عندما نستخدم الانضمام الداخلي بدلاً من الجلب ، فإن البيان الذي يطبعه هو:
Hibernate: حدد tuser0_.id as id1_0_ ، addresses1_.id as id0_1_ ، tuser0_.name as name1_0_ ، tuser0_.age as Age1_0_ ، addresses1_.address as address0_1_ ، address1_.user_id as user3_0_1_1_ tuser0_.id = addresses1_.user_id
يبدو أن العبارة ليست مختلفة ، ولكن عندما نكتشف ذلك ، فإنه يحصل على كائن [] نوع الصفيف ، لذلك تحتاج إلى الانتباه إلى هذا التحليل.
عندما لا نستخدم الجلب ولكن فقط انضم داخلي ، نحتاج إلى تحليله مثل هذا:
استعلام Query = Session.Createquery ("من Tuser usr Inner الانضمام إلى USR.Addresses") ؛ قائمة قائمة = Query.List () ؛ iterator iter = list.iterator () ؛ بينما (iter.hasnext ()) {object [] results = (object []) iter.next () ؛ لـ (int i = 0 ؛ i <results.length ؛ i ++) {system.out.println (النتائج [i]) ؛ }} نرى النتيجة المطبوعة:
org.hibernate.tutorial.domain6.tuser@16925b0 org.hibernate.tutorial.domain6.address@914f6a org.hibernate.tutorial.domain6.tuser@787d6a org.hibernate.tutorial.domain6. org.hibernate.tutorial.domain6.tuser@1326484 org.hibernate.tutorial.domain6.address@16546ef
كل من نتائجها هي الكائن المقابل.
2) الصلة الخارجية اليسرى ، وهذا يعادل الاتصال الأيسر من SQL. دعونا نلقي نظرة على المثال مباشرة:
من Tuser USR غادر Join Outer Join
عندما ندير البيان أعلاه ، يطبع السبات:
hibernate: حدد tuser0_.id as id1_0_ ، addresses1_.id as id0_1_ ، tuser0_.name as name1_0_ ، tuser0_.age ase1_0_ ، address1_.address as address0_1_ ، address1_.user_id as user3_0_1_ ، انضم إلى T_Address addresses1_ على tuser0_.id = addresses1_.user_id
لقد فحصناها في mysql ورأينا:
نرى أنه على الرغم من أن SHUN4 ليس لديه امتصاص مقابل ، إلا أنه لا يزال يتم اكتشافه. يشير Joft Outer Join إلى اكتشاف جميع السجلات في الجدول الأيسر.
لن أتحدث عن الموقف دون إحضاره هنا.
3) بعد ذلك ، دعونا نلقي نظرة على الانضمام الخارجي الأيمن. انطلاقًا من الاسم ، يجب أن يكون مرتبطًا بالانضمام الخارجي الأيسر. يمكننا أن نراها بوضوح من خلال النظر إلى الأمثلة مباشرة.
من Tuser USR اليمين الانضمام الخارجي جلب usr.addresses
نقوم بتنفيذها ونحصل على إخراج بيان النتيجة من السبات هو:
hibernate: حدد tuser0_.id as id1_0_ ، addresses1_.id as id0_1_ ، tuser0_.name as name1_0_ ، tuser0_.age ase1_0_ ، address1_.address as address0_1_ ، addresses1_.user_id as user3_0_1_ ، انضم إلى T_Address addresses1_ على tuser0_.id = addresses1_.user_idيمكننا أن نرى النتائج بعد التنفيذ في MySQL:
هنا يمكننا أن نرى أن العنوان هو test4 وليس لديه المستخدم المقابل المقابل له ، ولكن لا يزال من الممكن اكتشافه. يشير الصلة الخارجية اليمنى إلى اكتشاف جميع السجلات في الجدول الصحيح.
وضع الجلب هو على النحو الوارد أعلاه. إذا كنت لا تفهم ، فيمكنك إلقاء نظرة على الجلب الداخلي.