Curso de Java Spring Data JPA: Bases de Datos

Consultas con JPQL en Spring Data JPA

Curso de Java Spring Data JPA: Bases de Datos

Contenido del curso

Spring Data Repositories

Consultas con JPQL en Spring Data JPA

Platzi DayPlatzi Day

Todos los cursos GRATIS

Se acaba en:
:::

Resumen

Cuando trabajas con Spring Data JPA, llega un momento en que los query methods se quedan cortos y necesitas escribir consultas más expresivas sin renunciar a la orientación a objetos. Ahí entra JPQL, el lenguaje que te permite consultar la base de datos pensando en entities y atributos, no en tablas y columnas.

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

JPQL, Java Persistence Query Language, es un lenguaje de consulta orientado a objetos que opera sobre las clases entity de tu aplicación. En lugar de escribir from customer apuntando a una tabla, escribes from CustomerEntity apuntando a la clase mapeada.

¿Qué es JPQL? Es un lenguaje de consultas de Java Persistence que usa entities y sus atributos en vez de tablas y columnas. Spring lo traduce a SQL nativo en tiempo de ejecución.

La sintaxis se siente familiar si vienes de SQL: select, from, where. La diferencia está en que cada referencia apunta a una clase Java y a sus campos, lo que mantiene tu código alineado con el modelo de dominio.

¿Cómo crear un repositorio con @Query en JPQL?

El primer paso es definir una interfaz que extienda de ListCrudRepository, indicando el entity y el tipo de la clave primaria. En el ejemplo, CustomerEntity usa un String como identificador [01:00].

Dentro del repositorio se declara el método findByPhone, que recibe un phone y retorna un CustomerEntity. Aquí ya no se usan query methods basados en el nombre, sino la anotación @Query para escribir la consulta a mano:

java @Query("select c from CustomerEntity c where c.phoneNumber = :phone") CustomerEntity findByPhone(@Param("phone") String phone);

Fíjate en tres detalles que conviene revisar:

  • El alias c representa al entity CustomerEntity dentro de la consulta.
  • c.phoneNumber referencia el atributo de la clase, no la columna de la tabla.
  • Los dos puntos en :phone declaran un parámetro nombrado que luego se enlaza con @Param("phone").

La anotación @Param proviene de org.springframework.data.repository.query y sirve para que la consulta sepa exactamente qué argumento del método inyectar. Aunque el parámetro Java se llame igual, conviene declararlo siempre [01:55].

¿Cómo conectar el repositorio con un servicio?

El siguiente paso es crear CustomerService y anotarlo con @Service para que Spring lo registre como bean y pueda inyectar el repositorio. Si olvidas esa anotación, verás un error en el @Autowired aunque el constructor esté bien escrito [02:30].

El servicio expone un método findByPhone(String phone) que delega directamente en customerRepository.findByPhone(phone). Esa delegación deja el servicio limpio y mantiene la lógica de acceso a datos donde corresponde.

¿Cómo exponer la consulta con un controlador REST?

El controlador se anota con @Controller y @RequestMapping("/api/customers"), e inyecta el servicio por constructor. El uso explícito de @Autowired es opcional, pero ayuda a hacer visible que la dependencia la resuelve Spring.

El endpoint queda así:

  • @GetMapping("/phone/{phone}") define la ruta.
  • @PathVariable String phone captura el valor de la URL.
  • El método retorna ResponseEntity.ok(customerService.findByPhone(phone)).

¿Para qué sirve @PathVariable? Para extraer un valor que viaja como parte de la URL y pasarlo como argumento al método del controlador. Es la forma estándar de leer rutas dinámicas como /phone/{phone}.

Al ejecutar la aplicación y llamar /api/customers/phone/{numero} con un teléfono existente en la base pizzeria.customer, la respuesta llega con un 200 y el detalle del cliente: nombre, dirección, email, identificación y teléfono [03:45].

¿Cómo se traduce la consulta JPQL a SQL?

En la consola se ve la traducción que hace el motor: parte del JPQL escrito en el repositorio y genera un SQL nativo cuyo where filtra por phone_number. Esa equivalencia es la clave para entender por qué JPQL se siente cercano a SQL pero se escribe en términos del dominio.

La estructura se parece tanto que migrar mentalmente entre ambos cuesta poco. Aun así, hay un límite real: JPQL no soporta todas las características avanzadas del SQL nativo, como funciones específicas del motor, hints o sintaxis propietaria. Cuando necesitas eso, toca recurrir a @Query con nativeQuery = true.

¿Cuándo conviene usar JPQL frente a SQL nativo?

JPQL brilla cuando quieres mantener tu código portable entre motores de base de datos y trabajar con el modelo de objetos. SQL nativo gana cuando necesitas exprimir capacidades específicas del motor.

Una guía rápida para decidir:

  • Usa JPQL si la consulta se puede expresar con entities, joins básicos y filtros estándar.
  • Usa SQL nativo si necesitas funciones propias del motor, vistas materializadas o sintaxis no portable.
  • Usa query methods derivados del nombre cuando la consulta sea trivial y no quieras escribir nada.

¿Qué tipo de consultas estás resolviendo hoy con JPQL en tus proyectos? Cuéntame en los comentarios cómo decides entre query methods, JPQL y SQL nativo.