1. Introducción
En este tutorial, vamos a aprender sobre cómo limitar los resultados de las consultas utilizando la JPA y Spring Data JPA. Primero, examinaremos la tabla que queremos consultar, así como la consulta SQL que queremos reproducir. Luego, nos adentraremos en cómo lograr esto con JPA y Spring Data JPA. ¡Vamos a empezar!
2. Los Datos de Prueba
A continuación, tenemos la tabla que estaremos consultando a lo largo de este artículo. La pregunta que queremos responder es: “¿Cuál es el primer asiento ocupado y quién lo ocupa?”
First Name | Last Name | Seat Number |
---|---|---|
Jill | Smith | 50 |
Eve | Jackson | 94 |
Fred | Bloggs | 22 |
Ricki | Bobbie | 36 |
Siya | Kolisi | 85 |
3. La Consulta SQL
Con SQL, podríamos escribir una consulta que se vea algo así:
SELECT firstName, lastName, seatNumber FROM passengers ORDER BY seatNumber LIMIT 1;
Esta consulta selecciona el primer asiento disponible ordenado por el número de asiento, limitando el resultado a solo uno.
4. Configuración de JPA
Con JPA, primero necesitamos una entidad para mapear nuestra tabla:
@Entity
class Passenger {
@Id
@GeneratedValue
@Column(nullable = false)
private Long id;
@Basic(optional = false)
@Column(nullable = false)
private String firstName;
@Basic(optional = false)
@Column(nullable = false)
private String lastName;
@Basic(optional = false)
@Column(nullable = false)
private int seatNumber;
// constructor, getters, etc.
}
A continuación, necesitamos un método que encapsule nuestro código de consulta, implementado aquí como PassengerRepositoryImpl#findOrderedBySeatNumberLimitedTo(int limit)
:
@Repository
class PassengerRepositoryImpl {
@PersistenceContext
private EntityManager entityManager;
@Override
public List findOrderedBySeatNumberLimitedTo(int limit) {
return entityManager.createQuery("SELECT p FROM Passenger p ORDER BY p.seatNumber", Passenger.class)
.setMaxResults(limit)
.getResultList();
}
}
En nuestro método de repositorio, utilizamos el EntityManager para crear una Query en la que llamamos al método setMaxResults()
.
Esta llamada a Query#setMaxResults resultará en la sentencia limit añadida a la SQL generada:
select
passenger0_.id as id1_15_,
passenger0_.first_name as first_nam2_15_,
passenger0_.last_name as last_nam3_15_,
passenger0_.seat_number as seat_num4_15_
from passenger passenger0_ order by passenger0_.seat_number limit ?;
5. Con Spring Data JPA
También podemos generar nuestra SQL utilizando Spring Data JPA.
5.1. first
o top
Una forma de abordar esto es utilizando la derivación del nombre del método con las palabras clave first
o top
. Podemos, opcionalmente, especificar un número como el tamaño máximo de resultado que será devuelto. Si lo omitimos, Spring Data JPA asume un tamaño de resultado de 1.
Dado que queremos saber cuál fue el primer asiento ocupado y quién lo ocupa, podemos obtenerlo dejando el número en blanco de estas dos maneras:
Passenger findFirstByOrderBySeatNumberAsc();
Passenger findTopByOrderBySeatNumberAsc();
Si limitamos a una instancia de resultado, como se muestra arriba, también podemos envolver el resultado usando Optional
:
Optional findFirstByOrderBySeatNumberAsc();
Optional findTopByOrderBySeatNumberAsc();
5.2. Pageable
Alternativamente, podemos usar un Pageable:
Page page = repository.findAll(PageRequest.of(0, 1, Sort.by(Sort.Direction.ASC, "seatNumber")));
Si observamos la implementación predeterminada de JpaRepository, SimpleJpaRepository, podemos ver que también llama a Query#setMaxResults.
5.3. Usando Limit
Spring Data JPA versión 3.2 proporciona un nuevo tipo llamado Limit
para limitar el número de resultados devueltos de una consulta. Tiene dos métodos estáticos: of()
y unlimited()
. El método of()
acepta un entero como argumento. Limita los resultados de la consulta al tamaño máximo indicado, lo que permite obtener solo el número especificado de resultados.
A continuación, usaremos el método of()
de Limit
para limitar el resultado de la consulta a 1
:
List passenger = repository.findByOrderBySeatNumberAsc(Limit.of(1));
Aquí, invocamos el método estático of()
en Limit
para volver 1
resultado basado en nuestra especificación.
5.4. Comparación
Estas alternativas producen la SQL que estamos buscando, siendo first
y top
favorables a la convención, Pageable
a la configuración, y Limit
proporcionando una llamada simple al método:
select
passenger0_.id as id1_15_,
passenger0_.first_name as first_nam2_15_,
passenger0_.last_name as last_nam3_15_,
passenger0_.seat_number as seat_num4_15_
from passenger passenger0_ order by passenger0_.seat_number asc limit ?;
6. Conclusión
Limitar los resultados de consultas en JPA es ligeramente diferente de SQL; no incluimos la palabra clave limit directamente en nuestro JPQL. En su lugar, simplemente hacemos una única llamada al método Query#maxResults, o incluimos la palabra clave first
o top
en el nombre de nuestro método de Spring Data JPA.
Además, con Spring Data JPA versión 3.2 y superiores, podemos usar la interfaz Limit
para limitar los resultados de la consulta llamando a su método estático of()
para especificar el tamaño máximo.
Consejos Prácticos para Programadores Java
- Familiarízate con la configuración básica de JPA y Spring Data JPA antes de implementar consultas complejas.
- Utiliza
Optional
para manejar resultados nulos de manera más segura. - Considera usar
Limit
de manera eficiente si estás trabajando con una gran cantidad de datos, para mejorar el rendimiento. - No dudes en experimentar con derivación de métodos en Spring Data JPA para obtener consultas más limpias y legibles.
Con estos enfoques, podrás manejar tus consultas en JPA y Spring Data JPA de manera eficiente y efectiva, limitando los resultados según tus necesidades.