مرحبًا بكم في دليل تعليمي حول استخدام استعلامات Hibernate الأصلية للغة SQL. سبق لنا أن تناولنا لغة استعلام Hibernate و معايير Hibernate في المقالات السابقة، واليوم سنتناول استعلامات Hibernate الأصلية للغة SQL مع أمثلة توضيحية.
استعلامات Hibernate للغة SQL
يوفر Hibernate خيار تنفيذ استعلامات SQL الأصلية من خلال استخدام كائن SQLQuery. الاستعلام SQL في Hibernate مفيد جدًا عندما نحتاج إلى تنفيذ استعلامات خاصة ببائع قاعدة البيانات لا تدعمها واجهة برمجة التطبيقات في Hibernate. على سبيل المثال، تلميحات الاستعلام أو كلمة المفتاح CONNECT في قاعدة بيانات Oracle. بالنسبة للسيناريوهات العادية، ليس الاستعلام SQL في Hibernate الطريقة الموصى بها لأننا نفقد الفوائد المتعلقة بالرابطة Hibernate والذاكرة المؤقتة من المستوى الأول لهايبرنيت. سأستخدم قاعدة بيانات MySQL ونفس الجداول وإعدادات البيانات المستخدمة في مثال HQL، لذا يجب عليك التحقق من ذلك أولاً لفهم الجداول وتعيينات الفئات النمطية المقابلة.
مثال Hibernate Native SQL
للاستعلام الأصلي في Hibernate، نستخدم Session.createSQLQuery(String query)
لإنشاء كائن SQLQuery وتنفيذه. على سبيل المثال، إذا كنت ترغب في قراءة جميع السجلات من جدول الموظفين، يمكننا القيام بذلك من خلال الرمز التالي.
// العمل المسبق
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
// احصل على جميع الموظفين
Transaction tx = session.beginTransaction();
SQLQuery query = session.createSQLQuery("select emp_id, emp_name, emp_salary from Employee");
List
عند تنفيذ الشيفرة أعلاه لإعداد البيانات التي لدينا ، يتم إنتاج الناتج التالي.
Hibernate: select emp_id, emp_name, emp_salary from Employee
Id= 1, Name= Pankaj, Salary= 100.0, {Address= null}
Id= 2, Name= David, Salary= 200.0, {Address= null}
Id= 3, Name= Lisa, Salary= 300.0, {Address= null}
Id= 4, Name= Jack, Salary= 400.0, {Address= null}
لاحظ أن طريقة list()
تعيد قائمة من صفيف الكائنات ، ونحتاج إلى تحليلها بشكل صريح إلى double ، long وما إلى ذلك. تحتوي فئتان لدينا وعناوينهما على تنفيذات طريقة toString()
التالية.
@Override
public String toString() {
return "Id= " + id + ", Name= " + name + ", Salary= " + salary
+ ", {Address= " + address + "}";
}
@Override
public String toString() {
return "AddressLine1= " + addressLine1 + ", City=" + city
+ ", Zipcode=" + zipcode;
}
لاحظ أن استعلامنا لا يعيد بيانات العنوان ، في حين أنه إذا استخدمنا استعلام HQL "from Employee"
، فسيعيد بيانات الجدول المرتبط أيضًا.
استعلام Hibernate SQL addScalar
يستخدم Hibernate ResultSetMetadata
لاستنتاج نوع الأعمدة المُرجعة بواسطة الاستعلام ، من وجهة نظر الأداء ، يمكننا استخدام طريقة addScalar()
لتعريف نوع البيانات للعمود. ومع ذلك ، سنحصل على البيانات على شكل صفيف كائنات.
// الحصول على جميع الموظفين - مثال addScalar
query = session.createSQLQuery("select emp_id, emp_name, emp_salary from Employee")
.addScalar("emp_id", new LongType())
.addScalar("emp_name", new StringType())
.addScalar("emp_salary", new DoubleType());
rows = query.list();
for(Object[] row : rows){
Employee emp = new Employee();
emp.setId(Long.parseLong(row[0].toString()));
emp.setName(row[1].toString());
emp.setSalary(Double.parseDouble(row[2].toString()));
System.out.println(emp);
}
سيكون الناتج المولد هو نفسه ، ومع ذلك سنرى تحسينًا طفيفًا في الأداء عندما يكون حجم البيانات كبيرًا.
استعلام Hibernate Native SQL عدة جداول
إذا كنا نرغب في الحصول على البيانات من جدولي Employee و Address ، يمكننا ببساطة كتابة الاستعلام SQL لذلك وتحليل مجموعة النتائج.
query = session.createSQLQuery("select e.emp_id, emp_name, emp_salary,address_line1, city,
zipcode from Employee e, Address a where a.emp_id=e.emp_id");
rows = query.list();
for(Object[] row : rows){
Employee emp = new Employee();
emp.setId(Long.parseLong(row[0].toString()));
emp.setName(row[1].toString());
emp.setSalary(Double.parseDouble(row[2].toString()));
Address address = new Address();
address.setAddressLine1(row[3].toString());
address.setCity(row[4].toString());
address.setZipcode(row[5].toString());
emp.setAddress(address);
System.out.println(emp);
}
Hibernate: select e.emp_id, emp_name, emp_salary,address_line1, city, zipcode from Employee e, Address a where a.emp_id=e.emp_id
Id= 1, Name= Pankaj, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129}
Id= 2, Name= David, Salary= 200.0, {Address= AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051}
Id= 3, Name= Lisa, Salary= 300.0, {Address= AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100}
Id= 4, Name= Jack, Salary= 400.0, {Address= AddressLine1= City Centre, City=New Delhi, Zipcode=100100}
جافا هيبرنيت ناتيف إس كيو إل للكيان والانضمام
يمكننا أيضًا استخدام طرق addEntity()
و addJoin()
لاسترداد البيانات من الجدول المرتبط باستخدام الانضمام بين الجداول. على سبيل المثال ، يمكن أيضًا استرداد البيانات أعلاه على النحو التالي.
// مثال انضمام مع addEntity و addJoin
query = session.createSQLQuery("select {e.*}, {a.*} from Employee e join Address a ON e.emp_id=a.emp_id")
.addEntity("e",Employee.class)
.addJoin("a","e.address");
rows = query.list();
for (Object[] row : rows) {
for(Object obj : row) {
System.out.print(obj + "::");
}
System.out.println("\n");
}
// يُرجى ملاحظة أن الانضمام أعلاه يُرجع كل من كائني Employee و Address في المصفوفة
for (Object[] row : rows) {
Employee e = (Employee) row[0];
System.out.println("Employee Info::"+e);
Address a = (Address) row[1];
System.out.println("Address Info::"+a);
}
يُستخدم {[aliasname].*}
لإرجاع جميع الخصائص لكيان. عند استخدام addEntity()
و addJoin()
مع استعلامات الانضمام مثل ما هو مذكور أعلاه ، يُرجع كل من الكائنات ، كما هو مبين أعلاه. الإخراج الذي تنتجه الشيفرة أعلاه مثلما يلي.
Hibernate: select e.emp_id as emp_id1_1_0_, e.emp_name as emp_name2_1_0_, e.emp_salary as emp_sala3_1_0_, a.emp_id as emp_id1_0_1_, a.address_line1 as address_2_0_1_, a.city as city3_0_1_, a.zipcode as zipcode4_0_1_ from Employee e join Address a ON e.emp_id=a.emp_id
Id= 1, Name= Pankaj, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129}::AddressLine1= Albany Dr, City=San Jose, Zipcode=95129::
Id= 2, Name= David, Salary= 200.0, {Address= AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051}::AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051::
Id= 3, Name= Lisa, Salary= 300.0, {Address= AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100}::AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100::
Id= 4, Name= Jack, Salary= 400.0, {Address= AddressLine1= City Centre, City=New Delhi, Zipcode=100100}::AddressLine1= City Centre, City=New Delhi, Zipcode=100100::
Employee Info::Id= 1, Name= Pankaj, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129}
Address Info::AddressLine1= Albany Dr, City=San Jose, Zipcode=95129
Employee Info::Id= 2, Name= David, Salary= 200.0, {Address= AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051}
Address Info::AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051
Employee Info::Id= 3, Name= Lisa, Salary= 300.0, {Address= AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100}
Address Info::AddressLine1= BTM 1st Stage, City=Bangalore, Zipcode=560100
Employee Info::Id= 4, Name= Jack, Salary= 400.0, {Address= AddressLine1= City Centre, City=New Delhi, Zipcode=100100}
Address Info::AddressLine1= City Centre, City=New Delhi, Zipcode=100100
يمكنك تشغيل كل من الاستعلامين في عميل mysql ولاحظ أن الإخراج الذي ينتجه متطابق.
mysql> select e.emp_id as emp_id1_1_0_, e.emp_name as emp_name2_1_0_, e.emp_salary as emp_sala3_1_0_, a.emp_id as emp_id1_0_1_, a.address_line1 as address_2_0_1_, a.city as city3_0_1_, a.zipcode as zipcode4_0_1_ from Employee e join Address a ON e.emp_id=a.emp_id;
+--------------+----------------+----------------+--------------+----------------+-------------+---------------+
| emp_id1_1_0_ | emp_name2_1_0_ | emp_sala3_1_0_ | emp_id1_0_1_ | address_2_0_1_ | city3_0_1_ | zipcode4_0_1_ |
+--------------+----------------+----------------+--------------+----------------+-------------+---------------+
| 1 | Pankaj | 100 | 1 | Albany Dr | San Jose | 95129 |
| 2 | David | 200 | 2 | Arques Ave | Santa Clara | 95051 |
| 3 | Lisa | 300 | 3 | BTM 1st Stage | Bangalore | 560100 |
| 4 | Jack | 400 | 4 | City Centre | New Delhi | 100100 |
+--------------+----------------+----------------+--------------+----------------+-------------+---------------+
4 rows in set (0.00 sec)
mysql> select e.emp_id, emp_name, emp_salary,address_line1, city, zipcode from Employee e, Address a where a.emp_id=e.emp_id;
+--------+----------+------------+---------------+-------------+---------+
| emp_id | emp_name | emp_salary | address_line1 | city | zipcode |
+--------+----------+------------+---------------+-------------+---------+
| 1 | Pankaj | 100 | Albany Dr | San Jose | 95129 |
| 2 | David | 200 | Arques Ave | Santa Clara | 95051 |
| 3 | Lisa | 300 | BTM 1st Stage | Bangalore | 560100 |
| 4 | Jack | 400 | City Centre | New Delhi | 100100 |
+--------+----------+------------+---------------+-------------+---------+
4 rows in set (0.00 sec)
mysql>
جافا هيبرنيت ناتيف إس كيو إل استعلام مع معلمات
يمكننا أيضًا تمرير المعلمات إلى استعلامات Hibernate SQL، تمامًا مثل PreparedStatement JDBC. يمكن تعيين المعلمات باستخدام الاسم وكذلك الفهرس، كما هو موضح في المثال أدناه.
query = session
.createSQLQuery("select emp_id, emp_name, emp_salary from Employee where emp_id = ?");
List<Object[]> empData = query.setLong(0, 1L).list();
for (Object[] row : empData) {
Employee emp = new Employee();
emp.setId(Long.parseLong(row[0].toString()));
emp.setName(row[1].toString());
emp.setSalary(Double.parseDouble(row[2].toString()));
System.out.println(emp);
}
query = session
.createSQLQuery("select emp_id, emp_name, emp_salary from Employee where emp_id = :id");
empData = query.setLong("id", 2L).list();
for (Object[] row : empData) {
Employee emp = new Employee();
emp.setId(Long.parseLong(row[0].toString()));
emp.setName(row[1].toString());
emp.setSalary(Double.parseDouble(row[2].toString()));
System.out.println(emp);
}
الناتج الذي يتم إنتاجه بواسطة الشيفرة أعلاه سيكون:
Hibernate: select emp_id, emp_name, emp_salary from Employee where emp_id = ?
Id= 1, Name= Pankaj, Salary= 100.0, {Address= null}
Hibernate: select emp_id, emp_name, emp_salary from Employee where emp_id = ?
Id= 2, Name= David, Salary= 200.0, {Address= null}
هذا كل شيء لمقدمة موجزة حول استعلام Hibernate SQL، يجب تجنب استخدامه ما لم ترغب في تنفيذ استعلامات معينة لقاعدة البيانات.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-native-sql-query-example