Consultas personalizadas con JPQL y @Query

Clase 20 de 31Curso de Java: Backend con Spring Boot

Contenido del curso

JPA con Spring y Spring Data

Resumen

Construir consultas personalizadas es una necesidad frecuente cuando trabajamos con bases de datos en aplicaciones Spring Boot. JPQL (Java Persistence Query Language) ofrece una forma poderosa de escribir esas consultas directamente sobre objetos y propiedades de nuestras entidades, sin depender de la estructura de tablas en la base de datos. A continuación se explica cómo funciona y cómo integrarlo con la anotación @Query en un repositorio de Spring Data.

¿Qué es JPQL y en qué se diferencia de SQL?

JPQL es el lenguaje de consulta definido por JPA [0:12]. Su sintaxis es muy similar a SQL, pero existe una diferencia fundamental: mientras SQL trabaja con tablas y columnas, JPQL trabaja con objetos y propiedades de las entidades Java. Esto significa que en lugar de referenciar el nombre de una tabla en la base de datos, se referencia el nombre de la clase de la entidad.

Es importante tener en cuenta que JPQL permite realizar tres operaciones principales:

  • SELECT: consultar datos.
  • UPDATE: actualizar registros.
  • DELETE: eliminar registros.

No es posible ejecutar INSERT a través de JPQL [0:30]. Para insertar registros se utilizan otros mecanismos de JPA como el método save del repositorio.

¿Cómo se usa la anotación Query con JPQL?

La anotación @Query permite escribir consultas JPQL directamente sobre los métodos de un repositorio de Spring Data. Para ilustrarlo, se crea un método en la interfaz UserRepository que busca un usuario por su email [0:45].

java @Query("SELECT u FROM User u WHERE u.email = ?1") Optional<User> findByUserEmail(String email);

  • Optional<User> envuelve el resultado para manejar de forma segura los valores nulos.
  • La letra u actúa como un alias de la entidad User.
  • ?1 representa el primer parámetro que recibe el método.
  • La cláusula FROM referencia la entidad (User), no la tabla de la base de datos.

¿Cómo se consume este método en la aplicación?

Desde la clase principal FundamentosApplication se invoca el repositorio y se utiliza el patrón orElseThrow para lanzar una excepción cuando el usuario no existe [2:25]:

java userRepository.findByUserEmail("julie@domain.com") .orElseThrow(() -> new RuntimeException("No se encontró el usuario"));

Si el email existe, el resultado se imprime en los logs. Si no existe, se lanza un RuntimeException con el mensaje personalizado [3:15]. Este manejo de excepciones en tiempo de ejecución es clave para dar retroalimentación clara cuando una consulta no devuelve resultados.

¿Cómo ordenar resultados con JPQL y la clase Sort?

Spring Data permite combinar JPQL con la clase Sort de org.springframework.data.domain para ordenar los resultados dinámicamente [3:55]. Se define un método que recibe el nombre parcial de un usuario y un criterio de ordenamiento:

java @Query("SELECT u FROM User u WHERE u.name LIKE ?1%") List<User> findAndSort(String name, Sort sort);

  • El operador LIKE junto con el comodín % permite buscar usuarios cuyo nombre comience con el valor enviado.
  • La clase Sort define la propiedad y la dirección del ordenamiento.

Desde la clase principal se invoca así [4:30]:

java userRepository.findAndSort("user", Sort.by(Sort.Direction.DESC, "id")) .stream() .forEach(user -> logger.info("User with method sort: " + user));

Con Sort.Direction.DESC los usuarios se muestran del ID más alto al más bajo. Al cambiar a Sort.Direction.ASC, el orden se invierte mostrando primero los IDs menores [5:50].

¿Por qué algunos usuarios no aparecen en los resultados?

Cuando se envía "user" como parámetro de búsqueda, solo se devuelven los registros cuyo campo name comienza con esa cadena [5:30]. Usuarios con nombres como John, Julie o Daniela quedan excluidos porque sus nombres no coinciden con el patrón. Esto demuestra la precisión del operador LIKE en combinación con JPQL.

La flexibilidad de escribir consultas propias con @Query y JPQL permite adaptar cada método del repositorio a necesidades específicas del negocio, manteniendo la legibilidad del código y aprovechando las capacidades de Spring Data JPA para ordenar y filtrar datos de manera eficiente. Si ya utilizas derived query methods, incorporar JPQL te dará un control mucho más granular sobre tus consultas. ¿Qué tipo de consulta personalizada necesitas en tu proyecto? Comparte tu experiencia.

      Consultas personalizadas con JPQL y @Query