Dung (Donny) Nguyen

Senior Software Engineer

Spring Data JPA Repository Interfaces Explained

Spring Data JPA simplifies database access by providing a set of repository interfaces that allow you to define data access layers as plain Java interfaces. Spring automatically generates implementations at runtime based on the interface you extend and any additional query methods you declare (via method name conventions, @Query annotations, etc.).

The core idea is “repository” pattern abstraction: you declare what operations you need, and Spring Data JPA + JPA provider (like Hibernate) handles the underlying SQL/JPQL.

Repository Interface Hierarchy

All Spring Data repositories build on a marker interface:

The main practical interfaces form this inheritance chain (updated in recent Spring Data versions):

  1. CrudRepository<T, ID>
    Provides basic CRUD (Create, Read, Update, Delete) operations.
    It extends Repository<T, ID>.

    Key methods include:

    • S save(S entity) — saves or updates an entity
    • Optional<T> findById(ID id)
    • Iterable<T> findAll() (or List<T> in ListCrudRepository)
    • void delete(T entity) / void deleteById(ID id)
    • long count()
    • boolean existsById(ID id)
    • Iterable<S> saveAll(Iterable<S> entities)

    Use this when you need only simple CRUD without pagination or JPA-specific features.

  2. PagingAndSortingRepository<T, ID> (or ListPagingAndSortingRepository<T, ID> in newer versions)
    Extends CrudRepository and adds support for pagination and sorting.

    Additional key methods:

    • Iterable<T> findAll(Sort sort) (or List<T>)
    • Page<T> findAll(Pageable pageable) — returns a Page object with content, total elements, total pages, etc.

    Pageable combines page number, size, and Sort. This is essential for handling large datasets efficiently in web applications (e.g., with Spring MVC or REST).

  3. JpaRepository<T, ID>
    The most commonly used interface in Spring Data JPA applications.
    It extends PagingAndSortingRepository (and related list variants) plus QueryByExampleExecutor<T>.

    It inherits all CRUD + pagination/sorting methods and adds JPA-specific features:

    • void flush() — forces pending changes to the database
    • S saveAndFlush(S entity) — save + immediate flush
    • List<S> saveAllAndFlush(Iterable<S> entities)
    • void deleteInBatch(Iterable<T> entities) / void deleteAllInBatch() — batch deletes (more efficient than individual deletes)
    • T getReferenceById(ID id) — returns a proxy/reference (lazy loading friendly, formerly getOne())
    • Methods from QueryByExampleExecutor for querying by example (probe objects)

    JpaRepository is the go-to choice for most JPA-based projects because it provides the full feature set without extra boilerplate.

Other Notable Interfaces

How to Use Them

Here’s a typical example:

import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {

    // Derived query method (Spring parses the name and generates JPQL)
    Optional<User> findByEmail(String email);

    // Pagination + sorting example
    Page<User> findByActiveTrue(Pageable pageable);

    // Custom JPQL query
    @Query("SELECT u FROM User u WHERE u.username LIKE %:username%")
    List<User> findByUsernameContaining(@Param("username") String username);
}

Spring Boot auto-configures and scans for these interfaces (no @Repository annotation needed on the interface itself).

Best Practices

This abstraction layer drastically reduces boilerplate compared to writing raw JPA EntityManager code or plain JDBC. Spring Data JPA also supports query validation at startup, specifications (for dynamic predicates), and projections (DTO-like results without loading full entities).

For the absolute latest method signatures and changes (e.g., list-based variants), check the official Spring Data JPA reference documentation, as the framework evolves with new Spring versions.