How does pagination and sorting work with Pageable and Page?
Quick Answer
A repository method that accepts a Pageable parameter (typically built via PageRequest.of(pageNumber, pageSize, sort)) automatically applies the corresponding LIMIT/OFFSET and ORDER BY to its query, and returning a Page<T> (rather than a plain List<T>) additionally gives you the total element/page count, computed via an extra count query Spring Data generates automatically. Sort can be composed independently or combined into the Pageable itself, letting a single repository method support arbitrary client-driven paging and ordering without custom query code.
Detailed Answer
Spring Data JPA has built-in support for pagination and sorting via the Pageable and Sort abstractions, without requiring any custom LIMIT/OFFSET query logic.
Declaring a paginated repository method:
public interface OrderRepository extends JpaRepository<Order, Long> {
Page<Order> findByStatus(String status, Pageable pageable);
}
Building a Pageable and calling it:
Sort sort = Sort.by(Sort.Direction.DESC, "createdAt");
Pageable pageable = PageRequest.of(0, 20, sort); // page 0 (first page), 20 items per page, sorted
Page<Order> page = orderRepository.findByStatus("SHIPPED", pageable);
Spring Data translates this into the appropriate LIMIT/OFFSET (or database-specific equivalent) plus ORDER BY clause automatically — no manual SQL needed.
Page<T> vs Slice<T> vs plain List<T>:
Page<T>additionally providesgetTotalElements()andgetTotalPages()— but computing these requires Spring Data to run an additionalCOUNTquery alongside the main query, which has a real performance cost on very large tables.Slice<T>provideshasNext()/hasPrevious()(useful for infinite-scroll-style "load more" UIs) without the extra count query — cheaper when you don't actually need a total count.- A plain
List<T>combined with aPageableparameter still applies paging/sorting, but returns no metadata about total pages at all.
@RestController
class OrderController {
@GetMapping("/orders")
Page<Order> listOrders(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size,
@RequestParam(defaultValue = "createdAt,desc") String sort) {
Pageable pageable = PageRequest.of(page, size, Sort.by(parseSort(sort)));
return orderRepository.findByStatus("SHIPPED", pageable);
}
}
Spring MVC can also automatically resolve a Pageable method parameter directly from request query parameters (?page=0&size=20&sort=createdAt,desc) via PageableHandlerMethodArgumentResolver, which Spring Boot's web auto-configuration wires up by default — letting a controller accept a Pageable parameter directly without manually parsing query parameters at all.