Repository Abstractions

About

In a typical Java application, if we want to interact with a database (e.g., fetch, insert, update records), we would traditionally:

  • Write a DAO (Data Access Object) class manually

  • Inject an EntityManager

  • Manually create queries and handle exceptions

Spring Data JPA abstracts all that by providing a Repository Layer.

Repository Abstraction means:

Hiding the complexity of data access layers through ready-made interfaces, while still providing flexibility for customization.

Instead of writing SQL/JPQL and managing EntityManager code manually, we just define interfaces - Spring Data JPA takes care of the rest.

Evolution of Repository Abstractions

Level
Description

DAO Pattern

You create classes to manage database operations manually (classic way).

JPA EntityManager

Java EE way to persist entities with EntityManager.

Spring Data Repositories

Modern abstraction: You only define interfaces; implementation is created automatically.

Spring Data JPA builds a high-level abstraction on top of JPA and EntityManager.

Core Repository Interfaces in Spring Data

Spring Data JPA provides several base interfaces that we can extend:

Interface
Purpose

Repository<T, ID>

Base marker interface — No methods, just identifies a repository.

CrudRepository<T, ID>

Provides basic CRUD methods like save, findById, findAll, delete.

PagingAndSortingRepository<T, ID>

Extends CrudRepository and adds pagination and sorting capabilities.

JpaRepository<T, ID>

Extends PagingAndSortingRepository; adds JPA-specific methods like flush(), saveAll(), deleteInBatch().

QueryByExampleExecutor<T>

Allows query creation using Example (probe object) for dynamic search.

1. Repository<T, ID>

  • Pure marker interface — does not declare any method.

  • Purpose: Identify the type as a Repository for Spring Data to pick up.

2. CrudRepository<T, ID>

  • Provides basic CRUD operations:

Method
Description

save(S entity)

Save an entity.

findById(ID id)

Find an entity by its ID.

findAll()

Fetch all entities.

delete(T entity)

Delete an entity.

existsById(ID id)

Check if entity exists.

count()

Get count of entities.

3. PagingAndSortingRepository<T, ID>

  • Extends CrudRepository.

  • Adds pagination and sorting capabilities.

Method
Description

findAll(Pageable pageable)

Fetch paginated data.

findAll(Sort sort)

Fetch sorted data.

4. JpaRepository<T, ID>

  • Extends PagingAndSortingRepository.

  • Adds JPA-specific optimizations like:

Method
Description

flush()

Synchronizes persistence context to the database immediately.

saveAll(Iterable<S> entities)

Batch save entities.

deleteInBatch(Iterable<T> entities)

Batch delete.

findAllById(Iterable<ID> ids)

Find all entities matching IDs.

5. QueryByExampleExecutor<T>

  • Allows building queries using Example Matching instead of manual query methods.

Example:

No need to define explicit query methods.

How Repository Abstractions Work Internally ?

  • Spring Data JPA creates dynamic proxies for the repository interfaces.

  • Proxies interpret method names to generate SQL/JPQL automatically.

  • If we add @Query, it directly executes the provided query.

  • The proxy uses injected EntityManager to perform all operations.

No manual implementation needed. No manual query writing needed for simple cases.

Customizing Repositories

If default behavior isn't enough:

  • We can write custom methods manually (Custom Repository Implementation).

  • Or override default methods.

Then:

Last updated