Asignación de una consulta de Hibernación a una clase personalizada

1. Información general

Cuando usamos Hibernate para recuperar datos de la base de datos, de forma predeterminada, usa los datos recuperados para construir el gráfico de objeto completo para el objeto solicitado. Pero a veces es posible que deseemos recuperar solo una parte de los datos, preferiblemente en una estructura plana.

En este tutorial rápido, veremos cómo podemos lograr esto en Hibernate usando una clase personalizada.

2. Las Entidades

Primero, veamos las entidades que usaremos para recuperar los datos:

@Entity public class DeptEmployee { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String employeeNumber; private String designation; private String name; @ManyToOne private Department department; // constructor, getters and setters } @Entity public class Department { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String name; @OneToMany(mappedBy="department") private List employees; public Department(String name) { this.name = name; } // getters and setters  }

Aquí, tenemos dos entidades: DeptEmployee y Department . Para simplificar, supongamos que un empleado de departamento puede pertenecer a un solo departamento.

Sin embargo, un departamento puede tener varios empleados del departamento .

3. Una clase de resultado de consulta personalizada

Digamos que queremos imprimir una lista de todos los empleados con solo su nombre y el nombre de su departamento.

Normalmente, recuperaríamos estos datos con una consulta como esta:

Query query = session.createQuery("from com.baeldung.hibernate.entities.DeptEmployee"); List deptEmployees = query.list();

Esto recuperará a todos los empleados, todas sus propiedades, el departamento asociado y todas sus propiedades.

Pero, en este caso particular, esto puede resultar un poco caro ya que solo necesitamos el nombre del empleado y el nombre del departamento.

Una forma de recuperar solo la información que necesitamos es especificando las propiedades en la cláusula select.

Pero, cuando hacemos esto, Hibernate devuelve una lista de matrices en lugar de una lista de Objetos:

Query query = session.createQuery("select m.name, m.department.name from com.baeldung.hibernate.entities.DeptEmployee m"); List managers = query.list(); Object[] manager = (Object[]) managers.get(0); assertEquals("John Smith", manager[0]); assertEquals("Sales", manager[1]);

Como podemos ver, los datos devueltos son un poco engorrosos de procesar. Pero, afortunadamente, podemos hacer que Hibernate rellene estos datos en una clase.

Veamos la clase Result que usaremos para completar los datos recuperados en:

public class Result { private String employeeName; private String departmentName; public Result(String employeeName, String departmentName) { this.employeeName = employeeName; this.departmentName = departmentName; } public Result() { } // getters and setters }

Tenga en cuenta que la clase no es una entidad, sino solo un POJO. Sin embargo, también podemos usar una entidad siempre que tenga un constructor que tome todos los atributos que queramos completar como parámetros.

Veremos por qué el constructor es importante en la siguiente sección.

4. Usando un constructor en HQL

Ahora, veamos el HQL que usa esta clase:

Query query = session.createQuery("select new com.baeldung.hibernate.pojo.Result(m.name, m.department.name)" + " from com.baeldung.hibernate.entities.DeptEmployee m"); List results = query.list(); Result result = results.get(0); assertEquals("John Smith", result.getEmployeeName()); assertEquals("Sales", result.getDepartmentName());

Aquí, usamos el constructor que definimos en la clase Result junto con las propiedades que queremos recuperar. Esto devolverá una lista de objetos Result con los datos llenados de las columnas.

Como podemos ver, la lista devuelta es más fácil de procesar que usar una lista de matrices de objetos.

Es importante tener en cuenta que tenemos que usar el nombre completo de la clase en la consulta.

5. Usando un ResultTransformer

Una alternativa a usar un constructor en la consulta HQL es usar un ResultTransformer:

Query query = session.createQuery("select m.name as employeeName, m.department.name as departmentName" + " from com.baeldung.hibernate.entities.DeptEmployee m"); query.setResultTransformer(Transformers.aliasToBean(Result.class)); List results = query.list(); Result result = results.get(0); assertEquals("John Smith", result.getEmployeeName()); assertEquals("Sales", result.getDepartmentName());

Usamos los Transformers. aliasToBean () para utilizar los datos recuperados para completar los objetos Result .

En consecuencia, tenemos que asegurarnos de que los nombres de las columnas o sus alias en la instrucción select coincidan con las propiedades de la clase Result .

Tenga en cuenta que Query.setResultTransformer ( ResultTransformer ) ha quedado obsoleto desde Hibernate 5.2.

6. Conclusión

En este artículo, vimos cómo se puede usar una clase personalizada para recuperar datos en una forma fácil de leer.

El código fuente que acompaña a este artículo está disponible en GitHub.