Paginación y Ordenación con Spring Data Repositories

Clase 15 de 25Curso de Java Spring Data JPA: Bases de Datos

Contenido del curso

Spring Data Repositories

Resumen

Cuando una aplicación maneja grandes volúmenes de información, devolver todos los registros en una sola consulta no es eficiente ni práctico. Spring Data ofrece un repositorio especializado llamado PagingAndSortingRepository que permite paginar y ordenar los resultados de forma sencilla, controlando exactamente cuántos elementos se entregan por página y en qué orden.

¿Cómo crear un repositorio de paginación y ordenamiento?

El primer paso es crear una nueva interfaz que extienda de ListPagingAndSortingRepository en lugar del tradicional ListCrudRepository. Esta interfaz recibe dos parámetros genéricos: la entidad y el tipo de su clave primaria [01:00].

java public interface PizzaPageSortRepository extends ListPagingAndSortingRepository<PizzaEntity, Integer> { }

El nombre de la interfaz es descriptivo: PizzaPageSort indica que este repositorio se encargará de paginar y ordenar consultas sobre pizzas. A diferencia de un CRUD repository convencional, este repositorio expone un método findAll con dos variantes:

  • Recibe un objeto Sort cuando solo se necesita ordenar.
  • Recibe un objeto Pageable cuando se quiere paginar los resultados.

¿Qué cambios requiere el servicio para soportar paginación?

Dentro del servicio se inyecta el nuevo repositorio y se modifica el método getAll para que trabaje con paginación [02:08].

java @Service public class PizzaService { private final PizzaPageSortRepository pizzaPageSortRepository;

public Page<PizzaEntity> getAll(int page, int elements) { Pageable pageRequest = PageRequest.of(page, elements); return this.pizzaPageSortRepository.findAll(pageRequest); }

}

El objeto PageRequest se construye con el método estático of, que recibe dos parámetros enteros: el número de página (siempre empieza desde cero) y el tamaño de página, es decir, cuántos elementos contendrá cada página [02:30]. El tipo de retorno cambia de List a Page, ya que la respuesta ahora incluye metadatos de paginación.

¿Cómo se configura el controlador con request params?

En el controlador se reciben los parámetros page y elements usando la anotación @RequestParam, que es diferente a @PathVariable porque los valores viajan como parámetros de la petición en la URL y no como parte del path [03:10].

java @GetMapping public ResponseEntity<Page<PizzaEntity>> getAll( @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "8") int elements) { return ResponseEntity.ok(this.pizzaService.getAll(page, elements)); }

Una ventaja importante de @RequestParam es que permite definir un valor por defecto con el atributo defaultValue. En este caso, si no se envían parámetros, se devuelve la página cero con ocho elementos [03:38].

¿Qué estructura tiene la respuesta paginada?

Al consultar el endpoint sin parámetros, la respuesta ya no es una lista plana de pizzas. Ahora contiene una estructura enriquecida con los siguientes campos [04:15]:

  • content: el arreglo con los elementos de la página actual.
  • pageable: información sobre la paginación aplicada.
  • number: el número de página actual (comienza en cero).
  • size: la cantidad de elementos por página.
  • totalElements: el total de registros disponibles.
  • last: indica si es la última página.

Por ejemplo, con 13 pizzas y un tamaño de página de 8, el sistema indica que no es la última página y que se necesitan al menos dos páginas para cubrir todos los registros [04:48]. Si se cambia el tamaño a 15, todas las pizzas caben en una sola página y el campo last pasa a ser true [05:22].

¿Por qué es tan útil paginar consultas en Spring Data?

Cuando se trabaja con miles o millones de registros, enviar todo en una respuesta genera problemas de rendimiento tanto en el servidor como en el cliente. PagingAndSortingRepository resuelve esto de forma declarativa, sin necesidad de escribir consultas SQL manuales para limitar resultados. Solo hay que extender la interfaz correcta, usar PageRequest en el servicio y exponer los parámetros en el controlador.

Esta capacidad, combinada con los valores por defecto en los request params, permite ofrecer una API flexible donde el consumidor decide cuánta información recibir en cada llamada. Si te interesa explorar cómo agregar ordenamiento a esta misma estructura, comparte tus ideas en los comentarios.