Bienvenido al Tutorial de Ejemplo de Consulta Nombrada de Hibernate. Vimos cómo podemos usar HQL y Consulta SQL Nativa en Hibernate. Si hay muchas consultas, entonces causarán un desorden en el código porque todas las consultas estarán dispersas en todo el proyecto. Es por eso que Hibernate proporciona Consulta Nombrada que podemos definir en un lugar central y usarlas en cualquier parte del código. Podemos crear consultas nombradas tanto para HQL como para SQL Nativo.
Consulta Nombrada de Hibernate
La consulta con nombre de Hibernate se puede definir en archivos de mapeo de Hibernate o a través del uso de anotaciones JPA
@NamedQuery
y @NamedNativeQuery
. Hoy veremos ambos y cómo usar la consulta con nombre de Hibernate en una aplicación simple. Utilizaremos las mismas tablas de base de datos que en el Ejemplo de HQL, así que puedes revisar esa publicación para el script de configuración de la base de datos. Para nuestro ejemplo de proyecto de consulta con nombre de Hibernate, usaremos anotaciones para el mapeo de Hibernate. Sin embargo, crearemos algunas consultas con nombre tanto en archivos de mapeo como en clases de bean de entidad. Nuestra estructura de proyecto final se parece a la imagen a continuación, nos enfocaremos principalmente en los componentes relacionados con la Consulta con Nombre de Hibernate.
XML de Configuración de 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>
Consulta con nombre de Hibernate XML
Tenemos un archivo de mapeo de hibernate, que contiene solo consultas con nombre de HQL y consultas con nombre de SQL nativas. 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>
El elemento consulta se utiliza para consultas con nombre de HQL y el elemento sql-query se utiliza para consultas con nombre de SQL nativas. Podemos usar el elemento return para declarar la entidad a la que se mapeará el conjunto de resultados. return-join se utiliza cuando tenemos unión de múltiples tablas. Deberíamos usar CDATA para declarar nuestra consulta con nombre de hibernate para asegurarnos de que se trate como datos, de lo contrario, los signos < y > estropearán nuestro archivo de mapeo XML.
Consulta con nombre de HibernateAnotación @NamedQuery
Tenemos dos clases de modelo – Empleado
y Dirección
. Hemos definido consultas con nombre en la clase Dirección
como se muestra a continuación.
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;
}
}
Programa de prueba de consultas con nombre de Hibernate
Vamos a escribir un programa de prueba para usar todas las consultas nombradas de Hibernate definidas arriba.
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) {
// Trabajo preparatorio
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
// Ejemplo de Consulta Nombrada de 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());
}
// Ejemplo de Consulta Nombrada de SQL Nativo
query = session.getNamedQuery("@SQL_GET_ALL_ADDRESS");
List
Cuando ejecutamos el programa anterior con los datos de prueba que tenemos, produce la siguiente salida.
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
Puntos Importantes de la Consulta Nombrada de Hibernate
Algunos puntos importantes sobre la Consulta Nombrada de Hibernate son;
- La Consulta Nombrada de Hibernate nos ayuda a agrupar consultas en un lugar central en lugar de permitir que estén dispersas por todo el código.
- La sintaxis de la Consulta Nombrada de Hibernate se verifica cuando se crea la fábrica de sesiones de Hibernate, lo que hace que la aplicación falle rápidamente en caso de algún error en las consultas nombradas.
- La Consulta Nombrada de Hibernate es global, lo que significa que una vez definida se puede utilizar en toda la aplicación.
- Una de las principales desventajas de la consulta nombrada es que es difícil de depurar, porque necesitamos encontrar la ubicación donde está definida.
Eso es todo por el Ejemplo de Consulta Nombrada de Hibernate, puedes descargar el proyecto de muestra desde el siguiente enlace.
Source:
https://www.digitalocean.com/community/tutorials/hibernate-named-query-example-namedquery