Spring Data JPA
About
Spring Data JPA is a part of the larger Spring Data family. It is a framework that:
Simplifies the implementation of data access layers using JPA (Java Persistence API).
Reduces the amount of boilerplate code for repository classes.
Provides ready-to-use CRUD, pagination, sorting, query creation without writing any SQL/JPAQL manually (unless needed).
Integrates seamlessly with Hibernate (or any other JPA provider).
Why Spring Data JPA?
Traditional JPA (or Hibernate) involves a lot of repetitive code:
Spring Data JPA abstracts and automates these things by just providing an interface. Example:
No need to manually open/close EntityManager
, no manual queries for basic operations.
Components of Spring Data JPA
Repository Interfaces
Abstractions like JpaRepository
, CrudRepository
, PagingAndSortingRepository
for different functionalities.
Query Methods
Define methods in interfaces; Spring Data JPA automatically generates queries based on method names.
Custom Queries
Create your own JPQL/SQL queries using @Query
.
Specifications
Build dynamic, type-safe queries.
Projections
Fetch only required data instead of entire entity.
Auditing
Automatic tracking of entity creation, modification timestamps.
Pagination & Sorting
Built-in support for pageable results.
Transactional Support
Integrated with Spring’s @Transactional
management.
Commonly Used Spring Data JPA Interfaces
CrudRepository<T, ID>
Basic CRUD operations: save, find, delete.
PagingAndSortingRepository<T, ID>
Extends CrudRepository
; adds paging and sorting features.
JpaRepository<T, ID>
Extends PagingAndSortingRepository
; adds JPA-specific operations like batch delete, flush, etc.
JpaSpecificationExecutor<T>
Execute dynamic queries using JPA Criteria API (Specifications).
QueryByExampleExecutor<T>
Query entities based on example instances.
How Spring Data JPA Works Internally
When we define a simple repository interface like:
Spring Data JPA automatically provides the implementation of this interface at runtime — we do not have to implement it manually.
1
Spring Boot scans for Repository Interfaces during startup.
2
A Proxy (Dynamic Implementation) of the repository is created.
3
Proxy uses JpaRepositoryFactory to produce repository beans.
4
Proxy internally uses an EntityManager to perform operations.
5
Method names are parsed and converted into JPA Queries automatically.
6
Transactional behavior is automatically managed.
Step 1: Component Scanning
Spring Boot auto-configures JPA when it detects
spring-boot-starter-data-jpa
in the classpath.It scans the package and sub-packages for interfaces extending
JpaRepository
,CrudRepository
, or other repository markers.
The scan happens using annotations like:
Or if we don't explicitly configure it, Spring Boot auto-detects based on the location of your @SpringBootApplication
class.
Step 2: Repository Proxy Generation
Spring uses a dynamic proxy (
JDK Dynamic Proxy
orCGLIB Proxy
) to create a runtime implementation of your repository interface.This proxy does not contain any handwritten logic; instead, it delegates calls to the correct logic.
The key class responsible is:
org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean
This class creates a JpaRepositoryFactory
, which then builds a repository proxy.
Step 3: EntityManager Injection
Every generated repository proxy is injected with a JPA
EntityManager
.EntityManager
is the main API for persisting, finding, updating, and removing entities in JPA.
JpaEntityInformation
(meta-information about the entity) is also associated with each repository.
So when we call save()
, findById()
, etc., the proxy simply delegates to methods on EntityManager
like:
Step 4: Parsing Method Names into Queries
If we define a method like:
Spring Data JPA:
Parses method name (
findByDepartment
)Creates JPQL query:
This parsing is powered by:
org.springframework.data.repository.query.parser.PartTree
Spring does not require you to write the query manually unless it’s too complex.
Step 5: Executing Custom Queries
When we add:
Spring Data JPA detects the @Query
annotation and uses it instead of parsing the method name.
The execution pipeline is handled by SimpleJpaQuery
or custom QueryLookupStrategy
.
Step 6: Transaction Management
By default, Spring Data JPA repositories operate inside a transactional context.
The methods like
save()
,delete()
, etc., are automatically transactional.Spring Boot configures transaction management using
@EnableTransactionManagement
.
If needed, we can override by putting @Transactional(readOnly = true)
on repository methods.
Key Internal Classes Involved
JpaRepositoryFactoryBean
Responsible for creating repository proxies.
JpaRepositoryFactory
Creates repository implementations dynamically.
SimpleJpaRepository
Default implementation of repository logic.
EntityManager
Core JPA component for persistence operations.
PartTree
Parses query methods into JPQL.
QueryLookupStrategy
Strategy interface for looking up queries (derived, annotated, or named queries).
Example Internal Flow
Suppose we have this repository:
The behind-the-scenes flow will be:
1
Spring Boot scans and finds EmployeeRepository
.
2
JpaRepositoryFactoryBean
creates a dynamic proxy.
3
Proxy is linked to an EntityManager
.
4
You call findByName("John")
.
5
Proxy parses method → generates JPQL → binds parameter "John"
.
6
Query is executed via EntityManager
under a transactional context.
7
Result (List of Employees) is returned to you.
Last updated
Was this helpful?