ברוך הבא למדריך לדוגמאות שאילתות התואמות התשואה. חקרנו שפת שאילתות התואמות היברנייט ו- קריטריוני היברנייט במאמרים קודמים, היום נבחן שאילתות SQL טבעיות של היברנייט עם דוגמאות.
שאילתות SQL של היברנייט
התוכנה Hibernate מספקת אפשרות לביצוע שאילתות SQL נטיוות דרך השימוש באובייקט SQLQuery. שאילתות SQL של Hibernate הן נוחות מאוד כאשר עלינו לבצע שאילתות שהן מסוימות לספק מסד נתונים ואינן נתמכות על ידי קוד ה-API של Hibernate. לדוגמה, רמזי שאילתה או מילת המפתח CONNECT במסד הנתונים של Oracle. למצבים רגילים, שאילתות SQL של Hibernate אינן הדרך המומלצת מאחר ואנו מאבדים את היתרונות הקשורים לשיוך הייבוא ולמטמון הראשון של Hibernate. אשתמש במסד נתונים של MySQL ובאותם טבלאות והגדרת נתונים כמו בדוגמת HQL, כך שיש לך לבדוק תחילה כדי להבין את הטבלאות ואת מיפוי מחלקות המודל המתאים.
דוגמת SQL נטיבית של Hibernate
לשאילתות 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 הוספת סקלר
הייברנייט משתמש ב- ResultSetMetadata
כדי להסיק את סוג העמודות המוחזרות על ידי השאילתה, מנקודת מבט ביצועים, אנו יכולים להשתמש בשיטת 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);
}
הפלט שיופיע יהיה זהה, אך נראה שדברים ישתפרו קצת כאשר יש המון נתונים.
שאילתת Native SQL של Hibernate עם טבלאות מרובות
אם נרצה לקבל נתונים מטבלת עובדים ומטבלת כתובות, פשוט לכתוב את שאילתת ה-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");
}
//הצטרפות מעלה מחזירה גם אובייקטים של עובד וכתובת במערך
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);
}
{[שם כינוי].*}
משמשת להחזרת כל המאפיינים של אובייקט. כאשר אנו משתמשים ב-addEntity()
ו-addJoin()
עם שאילתות join כמו מעלה, היא מחזירה גם את האובייקטים, כפי שמוצג לעיל. הפלט שנוצר על ידי הקוד לעיל הוא כמו באילו:
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>
שאילתת SQL ישירה של Hibernate עם פרמטרים
יכולים גם להעביר פרמטרים לשאילתות SQL של Hibernate, בדיוק כמו JDBC PreparedStatement. ניתן להגדיר את הפרמטרים באמצעות השם וגם באמצעות האינדקס, כפי שמוצג בדוגמה למטה.
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}
זהו הכל להקדמה קצרה על שאילתות SQL של Hibernate, כדאי להימנע משימוש בהן אלא אם תרצה לבצע שאילתות ספציפיות לבסיס נתונים.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-native-sql-query-example