Spring Data JPA is a powerful tool for building Spring-powered applications that use JPA (Java Persistence API) for data access layers. It provides an extra layer of abstraction on top of existing JPA providers enabling applications to communicate with different data access technologies through a simple and consistent API.
The actual strength of Spring Data JPA lies in the repository abstraction. It abstracts the data store-specific implementation details and allows us to write the business logic code on a higher abstraction level.
We only need to learn how to use the Spring Data repository interfaces instead of worrying about these interfaces' implementation. Spring Data provides the implementation for these repository interfaces out of the box.
In this article, you'll learn in detail about different types of Spring Data repository interfaces and their features. There are three popular repository interfaces that you should know while using Spring Data JPA:
CrudRepository
— Interface for generic CRUD (Create, Read, Update, and Delete) operations on a repository for a specific type.PagingAndSortingRepository
— Extension ofCrudRepository
to provide additional methods to retrieve entities using the pagination and sorting abstraction.JpaRepository
— Extension ofPagingAndSortingRepository
to provide JPA-related methods such as flushing the persistence context and deleting records in a batch. Because of inheritance, it contains all functions of the first two repository interfaces.
All these repository interfaces directly or indirectly extend the top-level Spring Data Repository
interface. It acts as a central repository maker interface and captures the domain type to manage and the domain type's ID type.
Let us look at the CrudRepository
, PagingAndSortingRepository
, and JpaRepository
repositories and their methods.
CrudRepository
Interface
As the name suggests, the CrudRepository
interface defines a repository that provides standard CRUD methods for creating, reading, updating, and deleting entities.
Here is what the CrudRepository
interface definition looks like:
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
Optional<T> findById(ID id);
boolean existsById(ID id);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
long count();
void deleteById(ID id);
void delete(T entity);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
}
Let us now look at all the above methods one by one:
save()
— Saves a given entity. The persisted entity will be returned with all auto-generated and default fields being initialized.saveAll()
— Saves an iterable of entities. It returns all persisted entities as iterable.findById()
— Retrieves a single entity based on the primary key value.existsById()
— Returns whether an entity with the given ID exists.findAll()
— Returns an iterable of all existing entities of the type in the database.findAllById()
— Returns a iterable of all entities that match the given IDs.count()
— Returns the total number of entities available.deleteById()
— Deletes an entity with the given ID.delete()
— Finds and deletes the matching entity to the given entity.deleteAll()
— Deletes all entities that match in the given iterable. If no iterable is provided, it deletes all entities.
As you can see above, the CrudRepository
interface provides typical CRUD functionality for managing entities.
To use this repository interface in your application, just create a new Java interface that extends the CrudRepository
, as shown below:
public interface MovieRepository extends CrudRepository<Movie, Long> { }
Check out the Accessing Data with Spring Data JPA and MySQL tutorial to learn more about using
CrudRepository
for manipulating data.
PagingAndSortingRepository
Interface
The PagingAndSortingRepository
interface is an extension of CrudRepository
that provides two additional methods for applying dynamic pagination and sorting to query results.
Here is what the PagingAndSortingRepository
definition looks like:
@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {
Iterable<T> findAll(Sort sort);
Page<T> findAll(Pageable pageable);
}
findAll(Sort sort)
— Returns all entities sorted by the givenSort
object.findAll(Pageable pageable)
— Returns aPage
of entities that match the paging conditions provided by the givenPageable
object.
Let us create a new repository interface that extends the PagingAndSortingRepository
interface:
public interface SongRepository extends PagingAndSortingRepository<Song, Long> { }
To apply dynamic sorting to the query results, you need to create an instance of Sort
and pass it as a parameter to findAll()
:
Sort sort = Sort.by("title").descending();
List<Song> songs = songRepository.findAll(sort);
If you want to paginate the query results, you need to create an instance of the Pageable
interface as follows:
Pageable pageable = PageRequest.of(0, 10);
Page<Song> songs = songRepository.findAll(pageable);
You can even combine the sorting with the pagination by using the Pageable
interface:
Pageable pageable = PageRequest.of(0, 10, Sort.by("title").descending());
Page<Song> songs = songRepository.findAll(pageable);
JpaRepository
Interface
Finally, let us look at the JpaRepository
interface definition:
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort sort);
List<T> findAllById(Iterable<ID> ids);
<S extends T> List<S> saveAll(Iterable<S> entities);
void flush();
<S extends T> S saveAndFlush(S entity);
void deleteInBatch(Iterable<T> entities);
void deleteAllInBatch();
T getOne(ID id);
@Override
<S extends T> List<S> findAll(Example<S> example);
@Override
<S extends T> List<S> findAll(Example<S> example, Sort sort);
}
Most of the above JpaRepository
methods are inherited from the PagingAndSortingRepository
and QueryByExampleExecutor
interfaces. Let us look at the additional methods:
flush()
— Flushes all pending changes to the database.saveAndFlush()
— Saves the given entity and flushes changes instantly to the database.deleteInBatch()
— Deletes the given entities in a batch by using a single query.deleteAllInBatch()
— Deletes all entities in a batch call.getOne()
— Returns a single entity based on the given primary key value.
Since the JpaRepository
repository extends the PagingAndSortingRepository
, it inherits all methods from both the PagingAndSortingRepository
and CrudRepository
interfaces.
Using Spring Data Repositories
To use a Spring Data repository, you only need to create a new repository interface and extend any of the above-mentioned repositories.
The following example defines a CatRepository
interface by extending the Spring Data JPA's JpaRepository
and also declares query methods to retrieve Cat
entities from the database:
public interface CatRepository extends JpaRepository<Cat, Long> {
Cat findByName(String name);
List<Cat> findByColor(String color);
Page<Cat> findByAgeLessThan(int age, Pageable pageable)
}
Further Reading
To learn more about Spring Data JPA, check out the following articles:
- Getting Started with Spring Data JPA
- Spring Data JPA with H2 DataBase and Spring Boot
- Accessing Data with Spring Data JPA and MySQL
- Derived Query Methods in Spring Data JPA
- Spring Data JPA Custom Queries using @Query Annotation
- How to Use Spring Data JPA Named Queries
- Sorting Query Results in Spring Data JPA
- Pagination with Spring Data JPA
- Spring Data JPA One To One Relationship Mapping Example
- Spring Data JPA One To Many Relationship Mapping Example
- Spring Data JPA Many To Many Relationship Mapping Example
- Spring Data JPA Composite Primary Key Mapping Example
- Dynamic Queries with Spring Data JPA Specifications
✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.