What is the difference between CrudRepository and JpaRepository interfaces in Spring Data JPA?
When I see the examples on the web, I see them there used kind of interchangeably.
- What is the difference between them?
- Why would you want to use one over the other?
Basics
The base interface you choose for your repository has two main purposes. First, you allow the Spring Data repository infrastructure to find your interface and trigger the proxy creation so that you inject instances of the interface into clients. The second purpose is to pull in as much functionality as needed into the interface without having to declare extra methods.
The common interfaces
The Spring Data core library ships with two base interfaces that expose a dedicated set of functionalities:
CrudRepository
– CRUD methodsPagingAndSortingRepository
– methods for pagination and sorting (extendsCrudRepository
)Store-specific interfaces
The individual store modules (e.g. for JPA or MongoDB) expose store-specific extensions of these base interfaces to allow access to store-specific functionality like flushing or dedicated batching that take some store specifics into account. An example for this is
deleteInBatch(…)
ofJpaRepository
which is different fromdelete(…)
as it uses a query to delete the given entities which is more performant but comes with the side effect of not triggering the JPA-defined cascades (as the spec defines it).We generally recommend not to use these base interfaces as they expose the underlying persistence technology to the clients and thus tighten the coupling between them and the repository. Plus, you get a bit away from the original definition of a repository which is basically “a collection of entities”. So if you can, stay with
PagingAndSortingRepository
.Custom repository base interfaces
The downside of directly depending on one of the provided base interfaces is two-fold. Both of them might be considered as theoretical but I think they’re important to be aware of:
Page
orPageable
in your code anyway. Spring Data is not any different from any other general purpose library like commons-lang or Guava. As long as it provides reasonable benefit, it’s just fine.CrudRepository
, you expose a complete set of persistence method at once. This is probably fine in most circumstances as well but you might run into situations where you’d like to gain more fine-grained control over the methods expose, e.g. to create aReadOnlyRepository
that doesn’t include thesave(…)
anddelete(…)
methods ofCrudRepository
.The solution to both of these downsides is to craft your own base repository interface or even a set of them. In a lot of applications I have seen something like this:
The first repository interface is some general purpose base interface that actually only fixes point 1 but also ties the ID type to be
Long
for consistency. The second interface usually has all thefind…(…)
methods copied fromCrudRepository
andPagingAndSortingRepository
but does not expose the manipulating ones. Read more on that approach in the reference documentation.