Voorbeeld van een Hibernate Native SQL-query

Welkom bij de Hibernate Native SQL Query voorbeeld tutorial. We hebben eerder gekeken naar Hibernate Query Language en Hibernate Criteria in eerdere artikelen, vandaag zullen we kijken naar Hibernate Native SQL query met voorbeelden.

Hibernate SQL Query

Hibernate biedt de mogelijkheid om native SQL-query’s uit te voeren via het gebruik van het SQLQuery-object. Hibernate SQL Query is erg handig wanneer we databaseleverancierspecifieke query’s moeten uitvoeren die niet worden ondersteund door de Hibernate API. Bijvoorbeeld queryhints of het CONNECT-trefwoord in Oracle Database. Voor normale scenario’s is Hibernate SQL-query niet de aanbevolen aanpak omdat we voordelen verliezen met betrekking tot hibernate-associatie en hibernate first level cache. Ik zal MySQL-database gebruiken en dezelfde tabellen en gegevensopstelling gebruiken als in het HQL-voorbeeld, dus je moet dat eerst bekijken om de tabellen en de bijbehorende modelklassenmapping te begrijpen.

Voorbeeld van Hibernate Native SQL

Voor Hibernate Native SQL Query gebruiken we Session.createSQLQuery(String query) om het SQLQuery-object te maken en uit te voeren. Bijvoorbeeld, als je alle records van de Employee-tabel wilt lezen, kunnen we dat doen via onderstaande code.

// Voorbereiding
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();

// Haal Alle Medewerkers
Transaction tx = session.beginTransaction();
SQLQuery query = session.createSQLQuery("select emp_id, emp_name, emp_salary from Employee");
List 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);
}

Wanneer we bovenstaande code uitvoeren voor de gegevensopstelling die we hebben, wordt de volgende uitvoer geproduceerd.

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}

Merk op dat de list()-methode de lijst van Object-arrays retourneert. We moeten ze expliciet parseren naar double, long, enz. Onze Employee- en Address-klassen hebben de volgende implementaties van de 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;
}

Merk op dat onze query geen Address-gegevens retourneert, terwijl als we de HQL-query "from Employee" gebruiken, deze ook de bijbehorende tabelgegevens retourneert.

Hibernate SQL Query addScalar

Hibernate gebruikt ResultSetMetadata om het type van de kolommen die door de query worden geretourneerd af te leiden. Vanuit prestatieoogpunt kunnen we de addScalar()-methode gebruiken om het gegevenstype van de kolom te definiëren. We zouden echter nog steeds de gegevens in de vorm van een Object-array krijgen.

//Haal alle werknemers op - voorbeeld van 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);
}

De gegenereerde output zal hetzelfde zijn, maar we zullen een lichte prestatieverbetering zien wanneer de gegevens omvangrijk zijn.

Hibernate Native SQL Meerdere Tabellen

Als we gegevens uit zowel de Employee- als Address-tabellen willen halen, kunnen we eenvoudig de SQL-query daarvoor schrijven en het resultaatset parsen.

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);
}

Voor bovenstaande code wordt de uitvoer als volgt geproduceerd.

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 and Join

We kunnen ook de methoden addEntity() en addJoin() gebruiken om gegevens uit een geassocieerde tabel op te halen met behulp van tabel joins. Bijvoorbeeld, bovenstaande gegevens kunnen ook als volgt worden opgehaald.

//Voorbeeld van een join met addEntity en 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");
}
//Bovenstaande join retourneert zowel Employee als Address objecten in de 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);
}

{[aliasnaam].*} wordt gebruikt om alle eigenschappen van een entiteit terug te geven. Wanneer we addEntity() en addJoin() gebruiken met join queries zoals hierboven, retourneert het zowel de objecten, zoals hierboven weergegeven. De uitvoer die door bovenstaande code wordt geproduceerd, is als volgt.

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

Je kunt beide queries uitvoeren in de mysql-client en merken dat de geproduceerde uitvoer hetzelfde is.

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 Native SQL Query with Parameters

We kunnen ook parameters doorgeven aan de Hibernate SQL queries, net zoals JDBC PreparedStatement. De parameters kunnen worden ingesteld met behulp van zowel de naam als de index, zoals getoond in het onderstaande voorbeeld.

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);
}

De output die door de bovenstaande code wordt geproduceerd, is:

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}

Dat is alles voor een korte introductie van Hibernate SQL Query, je moet het vermijden tenzij je specifieke databasequery’s wilt uitvoeren.

Source:
https://www.digitalocean.com/community/tutorials/hibernate-native-sql-query-example