skip to content

Explain PagingAndSortingRepository. What changed about its position in the hierarchy in Spring Data 3.0?

level: seniorimportance: should knowfreq 40%

answer

  1. findAll(Sort) + findAll(Pageable)->Page
  2. Page = content + total metadata
  3. 3.0: no longer extends CrudRepository
  4. compose CRUD + paging separately now
  5. upgrade break: missing save/delete

basics

~10 s

PagingAndSortingRepository<T, ID> adds two methods: findAll(Sort) for sorted results and findAll(Pageable) returning a Page<T> for paginated results. In Spring Data 3.0 it stopped extending CrudRepository, so it no longer inherits save/delete.

solid answer

~40 s

PagingAndSortingRepository<T, ID> provides sorting and pagination: findAll(Sort sort) returns results in a given order, and findAll(Pageable pageable) returns a Page<T> — a slice plus metadata like total count, total pages, and whether more pages exist. Pageable carries page number, page size, and sort. The important 3.0 change: previously (Spring Data 2.x) PagingAndSortingRepository extended CrudRepository, so extending it gave you CRUD too. In Spring Data 3.0 it was decoupled — it now extends only Repository, so it no longer inherits save/findById/delete. If you want both CRUD and paging you must extend both interfaces (or extend JpaRepository/ListCrudRepository, which compose them). This was a deliberate move to make capabilities composable rather than a fixed inheritance chain. ListPagingAndSortingRepository is the List-returning variant of findAll(Sort).

code

java · 15 lines
java
// Spring Data 3.0+: compose both capabilities explicitly.
public interface OrderRepository
        extends CrudRepository<Order, Long>,
                PagingAndSortingRepository<Order, Long> {
}

// Usage:
Pageable pageable = PageRequest.of(0, 20, Sort.by("createdAt").descending());
Page<Order> page = repo.findAll(pageable);
long total = page.getTotalElements();  // triggers an extra count query
boolean more = page.hasNext();

List<Order> allSorted = /* if using ListPagingAndSortingRepository */
        repo instanceof ListPagingAndSortingRepository<Order,Long> lp
                ? lp.findAll(Sort.by("createdAt")) : List.of();

go deeper

for a junior

Know it provides findAll(Sort) and findAll(Pageable) returning a Page for pagination.

for a middle

Explain Pageable/PageRequest, Page metadata, and the extra count query for totals.

for a senior

Know the 3.0 decoupling from CrudRepository and how to compose CRUD + paging, plus the upgrade break.

for a principal

Discuss composable-capability design, Page vs Slice cost tradeoffs, and read-only repository surfaces via selective interface composition.

## What PagingAndSortingRepository offers `PagingAndSortingRepository<T, ID>` declares exactly **two** methods: 1. `Iterable<T> findAll(Sort sort)` — return **all** entities, ordered per the `Sort` (e.g. `Sort.by("lastName").ascending()`). No pagination — the whole table, just sorted. 2. `Page<T> findAll(Pageable pageable)` — return **one page** of entities. **`Pageable`** (usually `PageRequest.of(pageNumber, pageSize, sort)`) carries the zero-based page number, page size, and optional sort. **`Page<T>`** is the rich result: the content list for that page **plus metadata** — `getTotalElements()`, `getTotalPages()`, `getNumber()`, `getSize()`, `hasNext()`, `hasPrevious()`. Computing `getTotalElements()` requires an **extra `count` query**, which is why a lighter `Slice<T>` (no total count) exists for `Slice<T> findAll(Pageable)`-style derived queries when you don't need totals. ## The Spring Data 3.0 hierarchy change (the key interview point) - **Spring Data 2.x**: `PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID>`. So extending `PagingAndSortingRepository` transitively gave you all CRUD methods *plus* paging. - **Spring Data 3.0**: `PagingAndSortingRepository<T, ID> extends Repository<T, ID>` — **it no longer extends CrudRepository**. Extending it now gives you *only* the two paging/sorting methods, not `save`/`findById`/`delete`. **Why the change?** To make capabilities **composable and orthogonal** instead of forcing a linear inheritance chain. You now compose exactly the traits you want: - Need CRUD only → `CrudRepository` / `ListCrudRepository`. - Need paging only → `PagingAndSortingRepository` / `ListPagingAndSortingRepository`. - Need both → extend both, or extend a store interface like `JpaRepository` that already composes them. **Migration gotcha**: Code that extended `PagingAndSortingRepository` in 2.x and relied on inherited `save`/`delete` will **fail to compile** after upgrading to Spring Data 3.0 / Spring Boot 3.0 unless you also add `CrudRepository` (or switch to `JpaRepository`). This is a real, commonly-hit upgrade break. ## The List variant `ListPagingAndSortingRepository<T, ID>` extends `PagingAndSortingRepository` and overrides `findAll(Sort)` to return `List<T>` instead of `Iterable<T>`. It does **not** touch `findAll(Pageable)` since that already returns the rich `Page<T>`. ## When to use - Reach for `PagingAndSortingRepository` (or its List variant) when the repository needs server-side pagination/sorting but you deliberately want to *withhold* mutating CRUD from that interface — e.g. a read-oriented repository. Otherwise `JpaRepository` gives you everything. ## Gotchas - `Page` costs an extra count query; use `Slice` when you only need 'is there a next page?'. - Sorting/paging column names in `Sort`/`PageRequest` are **property names**, validated at runtime — a typo throws `PropertyReferenceException`.

  • You upgraded to Spring Boot 3 and your repository that extends only PagingAndSortingRepository no longer compiles because save() is missing. Why?
    In Spring Data 3.0, PagingAndSortingRepository no longer extends CrudRepository. Add CrudRepository (or ListCrudRepository), or switch to JpaRepository, to restore the CRUD methods.
  • What's the difference between Page and Slice?
    Page includes total element/page counts (requires an extra count query); Slice only knows whether a next slice exists (hasNext), avoiding the count query — cheaper for infinite-scroll style paging.

saying these in an interview costs you the question

  • Claiming PagingAndSortingRepository still extends CrudRepository in Spring Data 3.0
  • Saying findAll(Pageable) returns a plain List
  • Thinking Page never issues a count query

context