← All articles
Backend1 min read

Pagination and Sorting in Spring Data

Returning entire tables over HTTP is a scaling trap. Spring Data's Pageable makes paging and sorting a one-parameter change.

S

Swapnika Voora

Author

An endpoint that returns every row works fine with ten records and falls over at ten million. Spring Data bakes in pagination and sorting so you can return bounded, ordered slices without hand-writing LIMIT and OFFSET.

Accept a Pageable

Add a Pageable parameter to a repository method and Spring returns a Page that includes the content plus total counts.

ProductRepository.java
public interface ProductRepository extends JpaRepository<Product, Long> {
 
    Page<Product> findByCategory(String category, Pageable pageable);
}

Wire it through the controller

Spring MVC resolves Pageable straight from query parameters like ?page=0&size=20&sort=price,desc, so the controller stays clean.

ProductController.java
@GetMapping("/api/products")
public Page<ProductResponse> list(
        @RequestParam String category,
        Pageable pageable) {
    return repository.findByCategory(category, pageable)
        .map(ProductResponse::from);
}

Beware deep offset paging

OFFSET 100000 still scans and discards those rows. For large datasets, prefer keyset (cursor) pagination that seeks on an indexed column.

keyset.java
@Query("SELECT p FROM Product p WHERE p.id > :after ORDER BY p.id")
List<Product> findAfter(@Param("after") Long after, Pageable limit);

Takeaways

  • Never return unbounded collections from an API.
  • Pageable binds directly from page, size, and sort query params.
  • Switch to keyset pagination when offsets get large.

Cap the maximum page size server-side so a client can't request a million rows in one call.

#java#spring-boot#jpa#pagination

More in Backend