Exemple de requête SQL native Hibernate

Bienvenue dans le tutoriel sur l’exemple de requête SQL native Hibernate. Nous avons examiné le Langage de requête Hibernate et les Critères Hibernate dans des articles précédents, aujourd’hui nous examinerons la requête SQL native Hibernate avec des exemples.

Requête SQL Hibernate

Hibernate fournit une option pour exécuter des requêtes SQL natives grâce à l’utilisation de l’objet SQLQuery. La requête SQL Hibernate est très pratique lorsque nous devons exécuter des requêtes spécifiques au fournisseur de base de données qui ne sont pas prises en charge par l’API Hibernate. Par exemple, les indices de requête ou le mot-clé CONNECT dans Oracle Database. Pour les scénarios normaux, la requête SQL Hibernate n’est pas l’approche recommandée car nous perdons les avantages liés à l’association Hibernate et au cache de premier niveau Hibernate. Je vais utiliser la base de données MySQL et la même structure de tables et les mêmes données que celles utilisées dans l’exemple HQL, donc vous devriez consulter cela en premier pour comprendre les tables et la correspondance des classes de modèle correspondantes.

Exemple de requête SQL native Hibernate

Pour une requête SQL native Hibernate, nous utilisons Session.createSQLQuery(String query) pour créer l’objet SQLQuery et l’exécuter. Par exemple, si vous souhaitez lire tous les enregistrements de la table Employee, nous pouvons le faire avec le code suivant.

// Préparation
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();

// Obtenir tous les employés
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);
}

Lorsque nous exécutons le code ci-dessus pour la configuration des données que nous avons, il produit la sortie suivante.

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}

Remarquez que la méthode list() renvoie une liste d’objets du tableau, nous devons les convertir explicitement en double, long, etc. Nos classes Employee et Address ont les implémentations suivantes de la méthode 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;
}

Remarquez que notre requête ne renvoie pas les données de l’adresse, alors que si nous utilisons la requête HQL "from Employee", elle renvoie également les données de la table associée.

Requête SQL Hibernate avec addScalar

Hibernate utilise ResultSetMetadata pour déduire le type des colonnes renvoyées par la requête. Du point de vue des performances, nous pouvons utiliser la méthode addScalar() pour définir le type de données de la colonne. Cependant, nous obtiendrons toujours les données sous la forme d’un tableau d’objets.

// Récupération de tous les employés - exemple avec 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);
}

La sortie générée sera la même, mais nous verrons une légère amélioration des performances lorsque les données sont volumineuses.

Jointure de plusieurs tables avec SQL natif dans Hibernate

Si nous voulons obtenir des données à la fois des tables Employee et Address, nous pouvons simplement écrire la requête SQL correspondante et analyser le jeu de résultats.

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

Pour le code ci-dessus, la sortie produite sera comme suit.

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

Nous pouvons également utiliser les méthodes addEntity() et addJoin() pour récupérer les données de la table associée en utilisant les jointures de tables. Par exemple, les données ci-dessus peuvent également être récupérées comme suit.

//Exemple de jointure avec addEntity et 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");
}
//La jointure ci-dessus renvoie à la fois les objets Employee et Address dans le tableau
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].*} est utilisé pour renvoyer toutes les propriétés d’une entité. Lorsque nous utilisons addEntity() et addJoin() avec des requêtes de jointure comme ci-dessus, cela renvoie les deux objets, comme indiqué ci-dessus. La sortie produite par le code ci-dessus est comme suit.

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

Vous pouvez exécuter les deux requêtes dans le client mysql et constater que la sortie produite est la même.

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

Nous pouvons également passer des paramètres aux requêtes SQL Hibernate, tout comme JDBC PreparedStatement. Les paramètres peuvent être définis en utilisant le nom ainsi que l’index, comme indiqué dans l’exemple ci-dessous.

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

La sortie produite par le code ci-dessus serait :

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}

C’est tout pour une brève introduction à la requête SQL Hibernate, vous devriez éviter de l’utiliser à moins que vous souhaitiez exécuter des requêtes spécifiques à la base de données.

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