Repository Interfaces in Spring Data JPA
Repository interfaces are the core abstraction provided by Spring Data JPA to handle database operations.
They allow developers to perform CRUD and query operations without writing boilerplate DAO code, while still keeping full control when needed.
What is a Repository?
A repository is an interface that represents a collection like access to entities.
Instead of:
- Writing DAO classes
- Injecting
EntityManager - Writing repetitive CRUD code
You define an interface, and Spring generates the implementation automatically at runtime.
Think of a repository as a bridge between your domain model and the database.
Why Do We Need Repository Interfaces?
Without repositories:
- Every entity needs a DAO class
- CRUD logic is repeated
- Code becomes verbose and error-prone
- Maintenance becomes difficult
Repository interfaces:
- Reduce boilerplate
- Improve readability
- Encourage clean layering (Controller → Service → Repository)
- Let developers focus on business logic
Where Repositories Fit in the Application
Typical backend flow:
Controller → Service → Repository → Hibernate → Database
Important rules:
- Controllers should never talk directly to repositories
- Business logic belongs in the service layer
- Repositories should focus only on data access
Repository Hierarchy
Spring Data JPA provides a hierarchy of repository interfaces.
Repository (Marker Interface)
public interface Repository<T, ID> {
}
- Base marker interface
- Does not provide any methods
- Rarely used directly
CrudRepository
public interface CrudRepository<T, ID> extends Repository<T, ID> {
}
Provides basic CRUD operations:
- save()
- findById()
- findAll()
- deleteById()
Use when:
- Very simple CRUD requirements
- Minimal functionality needed
PagingAndSortingRepository
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
}
Adds:
- Pagination
- Sorting
Use when:
- Large result sets
- APIs need pageable responses
JpaRepository (Most Common)
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID> {
}
Adds:
- flush() - Flushes all pending changes to the database.
- saveAndFlush() - Saves an entity and flushes changes instantly.
- Batch operations
- JPA-specific behavior
JpaRepository is the most commonly used interface in real projects.
Use JpaRepository unless you have a strong reason not to.
Creating a Repository (Example)
@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
}
That’s it.
Spring automatically:
- Detects the interface
- Generates an implementation
- Registers it as a Spring bean
How Spring Creates Repository Implementations
At application startup:
- Spring scans for repository interfaces
- Creates proxy implementations
- Wires them into the application context
- Delegates calls to Hibernate internally
You never see the actual implementation class.
Repositories support:
- Derived query methods
- JPQL queries
- Native SQL queries
Example:
List<Customer> findByStatus(String status);
Notes:
- Repository implementations are generated at runtime
- JpaRepository is preferred in most cases
- Repositories should not contain business logic
- Pagination is critical for performance
- Repositories are Spring-managed beans