Skip to main content
Advertisement

9.5 Pagination and Sorting (Pageable)

When dealing with thousands of records, displaying them all on a single page is poor for performance and user experience. Spring Data JPA provides the Pageable interface to implement pagination and sorting easily.

1. Pageable and Page Interfaces

Spring Data JPA provides two core interfaces for handling pagination:

  • Pageable: An interface containing pagination request information (page number, size, and sorting criteria).
  • Page<T>: An interface that contains the resulting data list along with metadata like total pages and total elements.

2. Repository Layer Implementation

Simply add a Pageable parameter to your repository method.

public interface MemberRepository extends JpaRepository<Member, Long> {

// Search by name with pagination
Page<Member> findByNameContaining(String name, Pageable pageable);
}

3. Controller Layer Implementation

When you include Pageable as a parameter in a controller method, Spring automatically binds query parameters (e.g., ?page=0&size=10&sort=id,desc) to it.

@RestController
@RequestMapping("/api/members")
public class MemberController {

private final MemberRepository memberRepository;

@GetMapping
public Page<MemberResponseDto> getMembers(
@PageableDefault(size = 10, sort = "id", direction = Sort.Direction.DESC) Pageable pageable) {

return memberRepository.findAll(pageable)
.map(MemberResponseDto::from); // Convert Entity to DTO
}
}

Key Query Parameters

  • page: Page number (starting from 0).
  • size: Number of records per page.
  • sort: Sorting field and direction (sort=name,desc).

4. Understanding the Response Structure

Returning a Page<T> type includes rich metadata in the JSON response:

{
"content": [...], // Actual data list
"pageable": { ... }, // Pagination info
"totalElements": 105, // Total number of records
"totalPages": 11, // Total number of pages
"last": false, // Whether it's the last page
"size": 10, // Number of items per page
"number": 0, // Current page number
"sort": { ... }, // Sorting info
"numberOfElements": 10, // Number of items on current page
"first": true, // Whether it's the first page
"empty": false // Whether the result is empty
}

5. Page vs. Slice

  • Page<T>: Executes an additional count query to determine the total number of items (suitable for standard paginated lists).
  • Slice<T>: Only checks if a next page exists without a count query, providing better performance (suitable for infinite scrolls).
tip

In production environments with massive datasets, the count query can become a performance bottleneck. In such cases, consider using "Infinite Scroll" (Slice) or optimizing the count query with Querydsl.

Advertisement