Hibernate
Tutorial Hibernate: Consultas JPQL avanzadas
Hibernate consultas JPQL avanzadas: guía. Aprende a realizar consultas JPQL avanzadas en Hibernate mediante ejemplos prácticos y detallados.
Aprende Hibernate GRATIS y certifícateIntroducción
Java Persistence Query Language (JPQL) extiende las capacidades más allá de las consultas básicas, permitiendo operaciones complejas que incluyen el uso de JOIN
, GROUP BY
, HAVING
y subconsultas.
Estas características avanzadas habilitan la manipulación y el análisis profundo de datos relacionados entre diferentes entidades, agrupación de resultados, y la aplicación de condiciones a grupos de resultados, además de permitir consultas anidadas dentro de otras consultas.
Uso de JOIN para unir entidades
JPQL ofrece la capacidad de unir varias entidades mediante la cláusula JOIN
, lo que permite realizar consultas sobre relaciones entre entidades. Los tipos de JOIN
incluyen INNER JOIN
, LEFT JOIN
, RIGHT JOIN
, y FULL JOIN
, cada uno adecuado para distintos escenarios de consulta.
Consideremos un caso en el que necesitamos seleccionar todos los empleados y los departamentos a los que pertenecen. Suponiendo que cada entidad Empleado
tiene una relación con una entidad Departamento
, la consulta podría ser:
// Crear una instancia de Query para realizar un JOIN
jakarta.persistence.Query query = entityManager.createQuery("SELECT e, d FROM Empleado e JOIN e.departamento d");
// Ejecutar la consulta y recuperar la lista de resultados
List<Object[]> resultado = query.getResultList();
La consulta "SELECT e, d FROM Empleado e JOIN e.departamento d"
indica que deseamos seleccionar entidades Empleado
y sus respectivos Departamento
s:
SELECT e, d
: Esta parte de la consulta indica qué queremos obtener como resultado. Aquí, estamos diciendo que queremos seleccionar entidades completas, no solo campos individuales.e
representa a un objeto de la claseEmpleado
, yd
representa a un objeto de la claseDepartamento
. Al usarSELECT e, d
, estamos pidiendo que la consulta nos devuelva una lista de arrays, donde cada array contiene dos objetos: uno de la claseEmpleado
y otro de la claseDepartamento
.FROM Empleado e
: Aquí, especificamos de dónde queremos seleccionar los objetosEmpleado
. Usamose
como un alias para referenciar cualquier instancia deEmpleado
dentro de esta consulta. Es como decir: "Considera cada fila de la tablaEmpleado
(o cada instancia de la entidadEmpleado
) y refiérete a ella comoe
".JOIN e.departamento d
: Aquí se establece la relación entre las dos entidades que queremos unir en nuestra consulta.JOIN
es una operación que nos permite combinar filas de dos o más tablas (o entidades, en el caso de JPQL) basándose en una relación común entre ellas. En este caso,e.departamento
hace referencia a la propiedaddepartamento
dentro de la entidadEmpleado
. La parted
al final es un alias que usamos para referirnos a las instancias deDepartamento
que están relacionadas conEmpleado
a través de esta propiedad. Por lo tanto, la consulta une cada empleado (e
) con su respectivo departamento (d
) basándose en la relación definida en el modelo de datos de la aplicación.
Es decir, esta consulta JPQL nos permite traer juntos, en un solo resultado, a los empleados y sus respectivos departamentos, haciendo uso de la relación que existe entre estas dos entidades en el modelo de datos.
Agrupación de resultados con GROUP BY
La cláusula GROUP BY
se utiliza para agrupar los resultados de una consulta por uno o más atributos. Esto es especialmente útil cuando se combinan con funciones de agregación como COUNT
, MAX
, MIN
, SUM
, y AVG
.
Imaginemos que queremos contar el número de empleados en cada departamento:
// Preparar la consulta JPQL con agrupación
jakarta.persistence.Query query = entityManager.createQuery("SELECT d.nombre, COUNT(e) FROM Empleado e JOIN e.departamento d GROUP BY d.nombre");
// Ejecutar la consulta y recuperar los resultados
List<Object[]> resultado = query.getResultList();
La consulta "SELECT d.nombre, COUNT(e) FROM Empleado e JOIN e.departamento d GROUP BY d.nombre"
es un ejemplo de cómo podemos agrupar datos y aplicar funciones de agregación en un contexto donde las entidades están relacionadas:
SELECT d.nombre, COUNT(e)
: Esta es la parte de la consulta que define qué información queremos obtener como resultado. Aquí, estamos seleccionando dos cosas: el nombre del departamento (d.nombre
) y el número total de empleados (COUNT(e)
) que pertenecen a cada departamento.COUNT(e)
es una función de agregación que cuenta la cantidad de filas que cumplen con ciertos criterios, en este caso, cuántos empleados (e
) hay en cada departamento.FROM Empleado e
: Indica la entidad desde la cual estamos iniciando nuestra consulta. Usamose
como un alias para referirnos a las instancias de la entidadEmpleado
. Es decir, estamos diciendo que nuestra consulta va a trabajar sobre la tabla o entidadEmpleado
y que para esta consulta, nos referiremos a cada fila o instancia de esta entidad comoe
.JOIN e.departamento d
: Como en el ejemplo anterior, se unen estas dos entidades basándose en una relación existente entre ellas. En este caso, estamos diciendo que queremos unir cada empleado (e
) con su respectivo departamento.GROUP BY d.nombre
: La cláusulaGROUP BY
se usa para agrupar las filas que tienen el mismo valor en columnas especificadas, lo que permite realizar operaciones de agregación, como contar, sumar, promediar, etc., sobre cada grupo. En este caso, estamos agrupando los resultados por el nombre del departamento (d.nombre
). Esto significa que la consulta agrupará a todos los empleados según el departamento al que pertenecen, identificado por el nombre del departamento.
La consulta, por tanto, nos dará como resultado un conjunto de filas, donde cada fila contiene el nombre de un departamento y el número total de empleados que trabajan en ese departamento.
Uso de HAVING para filtrar grupos
La cláusula HAVING
se utiliza en combinación con GROUP BY
para aplicar condiciones a los grupos de resultados. Es similar a WHERE
, pero se aplica después de agrupar los resultados.
Si queremos encontrar departamentos con más de 10 empleados:
// Preparación de la consulta JPQL con HAVING
jakarta.persistence.Query query = entityManager.createQuery("SELECT d.nombre, COUNT(e) FROM Empleado e JOIN e.departamento d GROUP BY d.nombre HAVING COUNT(e) > 10");
// Ejecución de la consulta y recuperación de los resultados
List<Object[]> resultado = query.getResultList();
La consulta "SELECT d.nombre, COUNT(e) FROM Empleado e JOIN e.departamento d GROUP BY d.nombre HAVING COUNT(e) > 10"
filtra los grupos de resultados para incluir solo aquellos departamentos donde el conteo de empleados excede 10:
SELECT d.nombre, COUNT(e)
: Al igual que antes, se selecciona el nombre del departamento (d.nombre
) y el número total de empleados (COUNT(e)
) en cada departamento.FROM Empleado e
: Indica que la consulta se basa en la entidadEmpleado
, utilizandoe
como alias para referirse a las instancias de esta entidad.JOIN e.departamento d
: Esta instrucción une las entidadesEmpleado
yDepartamento
basándose en la relación definida entre ellas.GROUP BY d.nombre
: La consulta agrupa los resultados por el nombre del departamento (d.nombre
). Esto significa que todos los empleados se agruparán según el departamento al que pertenecen, y la función de agregación (COUNT(e)
) operará sobre estos grupos, contando cuántos empleados hay en cada uno.HAVING COUNT(e) > 10
: Aquí es donde esta consulta se distingue de la anterior. La cláusulaHAVING
funciona de manera similar aWHERE
, pero se aplica a grupos de resultados en lugar de a filas individuales. En este caso,HAVING COUNT(e) > 10
filtra los grupos resultantes para incluir solo aquellos que tienen más de 10 empleados. En otras palabras, después de que la consulta haya agrupado a los empleados por departamento y contado cuántos empleados hay en cada grupo,HAVING
elimina aquellos grupos (departamentos) que no cumplen con el criterio de tener más de 10 empleados.
El resultado final de esta consulta será un conjunto de filas, donde cada fila contiene el nombre de un departamento y el número total de empleados en ese departamento, pero solo para aquellos departamentos que tienen más de 10 empleados.
Subconsultas
Las subconsultas permiten realizar consultas dentro de otras consultas, proporcionando una poderosa herramienta para operaciones complejas de selección y filtrado.
Supongamos que queremos seleccionar todos los empleados cuyo salario es mayor que el promedio de salarios de la empresa:
// Crear una instancia de Query para una subconsulta
jakarta.persistence.Query query = entityManager.createQuery("SELECT e FROM Empleado e WHERE e.salario > (SELECT AVG(e2.salario) FROM Empleado e2)");
// Ejecutar la consulta y recuperar la lista de resultados
List<Empleado> resultado = query.getResultList();
La consulta "SELECT e FROM Empleado e WHERE e.salario > (SELECT AVG(e2.salario) FROM Empleado e2)"
resulta de unir dos consultas. La subconsulta (SELECT AVG(e2.salario) FROM Empleado e2)
calcula el salario promedio de todos los empleados. La consulta exterior selecciona aquellos empleados cuyo salario excede este promedio:
SELECT e FROM Empleado e
: Esta es la consulta principal. Indica que queremos seleccionar entidades completas de tipoEmpleado
.WHERE e.salario > (...subconsulta...)
: Esta parte de la consulta utiliza unWHERE
para limitar los resultados a aquellos empleados cuyo salario es mayor que el salario promedio de todos los empleados (que se obtiene de una subconsulta).SELECT AVG(e2.salario) FROM Empleado e2
: Esta es la subconsulta, que se ejecuta en el contexto de la consulta principal. La subconsulta calcula el salario promedio de todos los empleados. Usamose2
como un alias para las instancias deEmpleado
en esta subconsulta para diferenciarlas de las instancias referenciadas en la consulta principal (e
).AVG(e2.salario)
es una función de agregación que calcula el promedio de los salarios de todos los empleados.- La subconsulta se ejecuta primero, calculando el salario promedio de todos los empleados. Luego, este valor promedio se utiliza en la consulta principal como parte de la condición de filtrado
e.salario >
. Así, solo los empleados cuyo salario es mayor que este promedio son seleccionados y devueltos por la consulta principal.
El resultado de esta consulta será una lista de empleados que ganan más que el promedio de todos los salarios de los empleados, utilizando el mecanismo de subconsulta para calcular dinámicamente el valor de comparación basado en el conjunto de datos completo.
Ejercicios de esta lección Consultas JPQL avanzadas
Evalúa tus conocimientos de esta lección Consultas JPQL avanzadas con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Consultas JPQL avanzadas
Configuración con JPA
Tipos de datos personalizados
Consultas Criteria avanzadas
Operaciones en cascada
Anotaciones JPA
Asociación Many To One
Funciones en consultas JPQL
Asociación Many To Many entre Actor y Pelicula
Asociación One To Many entre Curso y Estudiante
Tipos de datos básicos
Consultas Criteria básicas
Asociación Many To Many
CRUD de entidades con asociaciones
Optimización de asociaciones con carga lazy
Asociación One To Many
Configuración con Maven
Asociación One To One
CRUD en Hibernate
Operaciones en cascada
Introducción a Hibernate
Atributos de tipo enum en entidades JPA
Carga de asociaciones en consultas con EntityGraph
Configuración con Gradle
Asociación One To One entre Libro y Resumen
Asociación One To Many
Asociación Many To Many
Creación de entidades
Ciclo de vida de una entidad
Consultas JPQL básicas
Carga de asociaciones en consultas con EntityGraph y anotaciones
Tipos de datos embebidos
Asociación Many To One entre Paciente y Clinica
Asociación Many To One
Optimización de consultas con DTOs
Atributos @Transient en entidades
Asociación One To One
Todas las lecciones de Hibernate
Accede a todas las lecciones de Hibernate y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Hibernate
Introducción Y Entorno
Configuración Hibernate Con Gradle
Introducción Y Entorno
Configuración Hibernate Con Maven
Introducción Y Entorno
Configuración Hibernate Con Jpa
Introducción Y Entorno
Tipos De Datos En Hibernate
Entidades Jpa Y Tipos De Datos
Atributos @Transient En Entidades
Entidades Jpa Y Tipos De Datos
Enums En Hibernate
Entidades Jpa Y Tipos De Datos
Tipos De Datos Embebidos
Entidades Jpa Y Tipos De Datos
Crud En Hibernate
Entidades Jpa Y Tipos De Datos
Ciclo De Vida De Una Entidad
Entidades Jpa Y Tipos De Datos
Creación De Entidades Jpa
Entidades Jpa Y Tipos De Datos
Asociación One To One
Asociaciones Entre Entidades
Asociación One To Many
Asociaciones Entre Entidades
Asociación Many To One
Asociaciones Entre Entidades
Asociación Many To Many
Asociaciones Entre Entidades
Operaciones En Cascada
Asociaciones Entre Entidades
Consultas Jpql Básicas
Consultas Hql Y Jpql
Consultas Jpql Avanzadas
Consultas Hql Y Jpql
Funciones En Consultas Jpql
Consultas Hql Y Jpql
Consultas Criteria Básicas
Api Criteria De Jpa
Consultas Criteria Avanzadas
Api Criteria De Jpa
Carga De Asociaciones En Consultas Con Entitygraph
Api Entitygraph
Carga De Asociaciones En Consultas Con Entitygraph Y Anotaciones
Api Entitygraph
Optimización De Consultas Con Dtos
Optimización
Optimización De Asociaciones Con Carga Lazy
Optimización
Certificados de superación de Hibernate
Supera todos los ejercicios de programación del curso de Hibernate y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el funcionamiento de las cláusulas
JOIN
en JPQL para unir diferentes entidades. - Aprender a usar
GROUP BY
para agrupar resultados de consultas por uno o más atributos. - Conocer el uso de
HAVING
para aplicar condiciones sobre los grupos de resultados en combinación conGROUP BY
. - Entender cómo realizar subconsultas dentro de otras consultas para operaciones complejas de selección y filtrado.