Hibernate Native SQL Query Beispiel-Tutorial
In früheren Artikeln haben wir uns Hibernate Query Language und Hibernate Criteria angesehen. Heute werden wir uns Hibernate Native SQL Query mit Beispielen ansehen.
Hibernate SQL Query
Hibernate bietet die Möglichkeit, native SQL-Abfragen mit dem SQLQuery
-Objekt auszuführen. Hibernate SQL Query ist sehr nützlich, wenn wir datenbankspezifische Abfragen ausführen müssen, die von der Hibernate-API nicht unterstützt werden, z. B. Abfragehinweise oder das CONNECT
-Schlüsselwort in Oracle-Datenbanken.
Für normale Szenarien ist Hibernate SQL Query nicht die empfohlene Methode, da wir Vorteile in Bezug auf Hibernate-Assoziationen und den Hibernate-First-Level-Cache verlieren. Ich werde die MySQL-Datenbank sowie dieselben Tabellen und Dateneinstellungen wie im HQL-Beispiel verwenden. Sie sollten sich dieses zuerst ansehen, um die Tabellen und die entsprechende Zuordnung der Modellklassen zu verstehen.
Beispiel
Für Hibernate Native SQL Query verwenden wir Session.createSQLQuery(String query)
, um das SQLQuery
-Objekt zu erstellen und auszuführen. Wenn Sie z. B. alle Datensätze aus der Employee-Tabelle lesen möchten, können wir dies mit folgendem Code tun:
// Prep work
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
// Get All Employees
Transaction tx = session.beginTransaction();
SQLQuery query = session.createSQLQuery("select emp_id, emp_name, emp_salary from Employee");
List<Object[]> 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);
}
Wenn wir den obigen Code für das eingerichtete Datenset ausführen, erhalten wir folgende Ausgabe:
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}
Beachten Sie, dass die list()
-Methode eine Liste von Objektarrays zurückgibt. Wir müssen sie explizit in double
, long
usw. analysieren. Unsere Employee- und Address-Klassen haben folgende Implementierungen der toString()
-Methode:
@Override
public String toString() {
return "Id= " + id + ", Name= " + name + ", Salary= " + salary
+ ", {Address= " + address + "}";
}
@Override
public String toString() {
return "AddressLine1= " + addressLine1 + ", City=" + city
+ ", Zipcode=" + zipcode;
}
Beachten Sie, dass unsere Abfrage keine Adressdaten zurückgibt, während die HQL-Abfrage "from Employee"
auch die Daten der zugehörigen Tabelle zurückgibt.
Hibernate SQL Query addScalar
Hibernate verwendet ResultSetMetadata
, um den Typ der von der Abfrage zurückgegebenen Spalten abzuleiten. Aus Performance-Sicht können wir die Methode addScalar()
verwenden, um den Datentyp der Spalte zu definieren. Die Daten würden jedoch weiterhin in Form eines Objektarrays vorliegen:
// Get All Employees - addScalar example
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);
}
Die generierte Ausgabe wird dieselbe sein, wir werden jedoch eine leichte Leistungsverbesserung feststellen, wenn die Datenmenge groß ist.
Hibernate SQL Abfragen über mehrere Tabellen
Wenn wir Daten aus den Tabellen Employee und Address abrufen möchten, können wir die entsprechende SQL-Abfrage schreiben und das Ergebnis analysieren.
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);
}
Für den obigen Code wird die folgende Ausgabe generiert:
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}
Hibernate Native SQL Entity und Join
Wir können auch die Methoden addEntity()
und addJoin()
verwenden, um Daten aus verknüpften Tabellen über Joins abzurufen. Zum Beispiel können die obigen Daten auch wie folgt abgerufen werden:
// Join example with addEntity and 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");
}
// Above join returns both Employee and Address Objects in the array
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].*}
wird verwendet, um alle Eigenschaften einer Entität zurückzugeben. Wenn wir addEntity()
und addJoin()
mit Join-Abfragen wie oben verwenden, gibt es beide Objekte zurück, wie oben gezeigt. Die generierte Ausgabe sieht wie folgt aus:
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}
Address Info::AddressLine1= Albany Dr, City=San Jose, Zipcode=95129
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
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
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
Sie können beide Abfragen im MySQL-Client ausführen und feststellen, dass die erzeugte Ausgabe identisch ist.
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-Abfrage mit Parametern
Wir können auch Parameter an die Hibernate SQL-Abfragen übergeben, ähnlich wie bei JDBC PreparedStatement
. Die Parameter können sowohl mit Namen als auch mit Index gesetzt werden, wie im folgenden Beispiel gezeigt:
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);
}
Die durch den obigen Code erzeugte Ausgabe wäre:
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
Id= 2, Name= David, Salary= 200.0, {Address= null}
Das war eine kurze Einführung in Hibernate SQL Query. Sie sollten diese Methode vermeiden, es sei denn, Sie müssen datenbankspezifische Abfragen ausführen.