ברוכים הבאים למדריך לדוגמא של שאילתא בשם ב-Hibernate. ראינו כיצד אנו יכולים להשתמש ב-HQL וב-שאילתת SQL ילידית ב-Hibernate. אם ישנן הרבה שאילתות, אז הן יגרמו לבלאגן בקוד מאחר וכל השאילתות יהיו מתפזרות לאורך כל הפרויקט. זו הסיבה שבגללה Hibernate מספקת שאילתה בשם שאנו יכולים להגדיר במיקום מרכזי ולהשתמש בהן בכל מקום בקוד. אנו יכולים ליצור שאילתות בשם עבור HQL וגם SQL ילידית.
שאילתה בשם ב-Hibernate
שאילתת שם Hibernate ניתן להגדיר בקבצי מיפוי של Hibernate או דרך השימוש בהערות JPA
@NamedQuery
ו- @NamedNativeQuery
. היום נבחן את שניהם וכיצד להשתמש בשאילתה בשם Hibernate ביישום פשוט. נשתמש באותם טבלאות מסד נתונים כמו בדוגמה של דוגמת HQL, כך שתוכל לבדוק את התסריט של מסד הנתונים להתקנה. לדוגמה של השאילתה בשם שלנו בהגדרת הפרויקט, נשתמש בהערות למיפוי Hibernate. עם זאת, ניצור כמה שאילתות בשם בקבצי מיפוי ובמחלקות הישות. מבנה הפרויקט הסופי שלנו נראה כמו בתמונה למטה, ונרכז בעיקר ברכיבים הקשורים לשאילתה בשם Hibernate.
קובץ XML של תצורת Hibernate
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "https://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.password">pankaj123</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/TestDB</property>
<property name="hibernate.connection.username">pankaj</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<mapping class="com.journaldev.hibernate.model.Employee" />
<mapping class="com.journaldev.hibernate.model.Address" />
<mapping resource="named-queries.hbm.xml" />
</session-factory>
</hibernate-configuration>
שאילתת השמות של Hibernate XML
יש לנו קובץ מיפוי של היברנייט, שמכיל רק שאילתות בשמות HQL ושאילתות בשמות של SQL גולמי. named-queries.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<query name="HQL_GET_ALL_EMPLOYEE">from Employee</query>
<query name="HQL_GET_EMPLOYEE_BY_ID">
<![CDATA[from Employee where emp_id = :id]]>
</query>
<query name="HQL_GET_EMPLOYEE_BY_SALARY">
<![CDATA[from Employee where emp_salary > :salary]]>
</query>
<sql-query name="SQL_GET_ALL_EMPLOYEE">
<![CDATA[select emp_id, emp_name, emp_salary from Employee]]>
</sql-query>
<sql-query name="SQL_GET_ALL_EMP_ADDRESS">
<![CDATA[select {e.*}, {a.*} from Employee e join Address a ON e.emp_id=a.emp_id]]>
<return alias="e" class="com.journaldev.hibernate.model.Employee" />
<return-join alias="a" property="e.address"></return-join>
</sql-query>
</hibernate-mapping>
אלמנט שאילתה משמש לשאילתות בשמות HQL ואלמנט שאילתת- sql משמש לשאילתות בשמות SQL גולמי. אנו יכולים להשתמש באלמנט החזרה להצהרת היישות שאליה תתאים קבוצת התוצאות. הצטרפות-חזרה משמש כאשר יש לנו הצטרפות של מספר טבלאות. עלינו להשתמש ב-CDATA כדי להכריז על שאילתת השמות שלנו בהיברנייט כדי לוודא שהיא מטופלת כנתונים, אחרת הסימנים < ו-> יפגיעו בקובץ ה-XML של המיפוי שלנו.
שאילתת השמות של היברנייט@NamedQuery הערת תיעוד
יש לנו שני מחלקות מודל – עובד
ו- כתובת
. הגדרנו שאילתות בשמות במחלקת כתובת
כך שמוצג למטה.
package com.journaldev.hibernate.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
@Entity
@Table(name = "ADDRESS")
@NamedQueries({ @NamedQuery(name = "@HQL_GET_ALL_ADDRESS",
query = "from Address") })
@NamedNativeQueries({ @NamedNativeQuery(name = "@SQL_GET_ALL_ADDRESS",
query = "select emp_id, address_line1, city, zipcode from Address") })
public class Address {
@Id
@Column(name = "emp_id", unique = true, nullable = false)
@GeneratedValue(generator = "gen")
@GenericGenerator(name = "gen", strategy = "foreign", parameters = { @Parameter(name = "property", value = "employee") })
private long id;
@Column(name = "address_line1")
private String addressLine1;
@Column(name = "zipcode")
private String zipcode;
@Column(name = "city")
private String city;
@OneToOne
@PrimaryKeyJoinColumn
private Employee employee;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
@Override
public String toString() {
return "AddressLine1= " + addressLine1 + ", City=" + city
+ ", Zipcode=" + zipcode;
}
}
מבחן ניתוח שאילתות בשמות של היברנייט
נכתוב תוכנית מבחן לשימוש בכל השאילתות ששמות הוגדרו למעלה בהיברנייט.
package com.journaldev.hibernate.main;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Address;
import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;
public class HibernateNamedQueryExample {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// עבודת הכנה
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
//דוגמה לשאילתת שאלות ב-HQL
Query query = session.getNamedQuery("HQL_GET_ALL_EMPLOYEE");
List empList = query.list();
for (Employee emp : empList) {
System.out.println("List of Employees::" + emp.getId() + ","
+ emp.getAddress().getCity());
}
query = session.getNamedQuery("HQL_GET_EMPLOYEE_BY_ID");
query.setInteger("id", 2);
Employee emp = (Employee) query.uniqueResult();
System.out.println("Employee Name=" + emp.getName() + ", City="
+ emp.getAddress().getCity());
query = session.getNamedQuery("HQL_GET_EMPLOYEE_BY_SALARY");
query.setInteger("salary", 200);
empList = query.list();
for (Employee emp1 : empList) {
System.out.println("List of Employees::" + emp1.getId() + ","
+ emp1.getSalary());
}
query = session.getNamedQuery("@HQL_GET_ALL_ADDRESS");
List addressList = query.list();
for (Address addr : addressList) {
System.out.println("List of Address::" + addr.getId() + "::"
+ addr.getZipcode() + "::" + addr.getEmployee().getName());
}
//דוגמה לשאילתת שאלות ב-Native SQL
query = session.getNamedQuery("@SQL_GET_ALL_ADDRESS");
List
כאשר אנו מפעילים את התוכנית למעלה עם נתוני הבדיקה שלנו, היא מפיקה את הפלט הבא.
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
Hibernate: select address0_.emp_id as emp_id1_0_0_, address0_.address_line1 as address_2_0_0_, address0_.city as city3_0_0_, address0_.zipcode as zipcode4_0_0_, employee1_.emp_id as emp_id1_1_1_, employee1_.emp_name as emp_name2_1_1_, employee1_.emp_salary as emp_sala3_1_1_ from ADDRESS address0_ left outer join EMPLOYEE employee1_ on address0_.emp_id=employee1_.emp_id where address0_.emp_id=?
List of Employees::1,San Jose
List of Employees::2,Santa Clara
List of Employees::3,Bangalore
List of Employees::4,New Delhi
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ where emp_id=?
Employee Name=David, City=Santa Clara
Hibernate: select employee0_.emp_id as emp_id1_1_, employee0_.emp_name as emp_name2_1_, employee0_.emp_salary as emp_sala3_1_ from EMPLOYEE employee0_ where emp_salary>?
List of Employees::3,300.0
List of Employees::4,400.0
Hibernate: select address0_.emp_id as emp_id1_0_, address0_.address_line1 as address_2_0_, address0_.city as city3_0_, address0_.zipcode as zipcode4_0_ from ADDRESS address0_
List of Address::1::95129::Pankaj
List of Address::2::95051::David
List of Address::3::560100::Lisa
List of Address::4::100100::Jack
Hibernate: select emp_id, address_line1, city, zipcode from Address
1::Albany Dr::San Jose::95129::
2::Arques Ave::Santa Clara::95051::
3::BTM 1st Stage::Bangalore::560100::
4::City Centre::New Delhi::100100::
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
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
נקודות חשובות על שאילתות שמות בהיברנייט
כמה נקודות חשובות על שאילתות שמות בהיברנייט הם:
- שאילתות שמות בהיברנייט עוזרות לנו לקבץ שאילתות במקום מרכזי במקום לאפשר להן להתפזר בכל רחבי הקוד.
- תחביר שאילתות שמות בהיברנייט מאומת בעת יצירת מתוך המפעל של היברנייט, כך שהיישום נכשל מהר במקרה של כל שגיאה בשאילתות השמות.
- שאילתות שמות בהיברנייט הן גלובליות, כלומר פעם אחת הוגדרו ניתן להשתמש בהן בכל היישום.
- אחד החסרונות העיקריים של שאילתת שמות הוא שקשה לנו לנפח אותה, מכיוון שאנו צריכים למצוא את המיקום בו הוגדרה.
זהו הכל לדוגמה על שאילתת שמות בהיברנייט, תוכלו להוריד את הפרויקט הדוגמא מהקישור למטה.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-named-query-example-namedquery