Spring Data JPA Custom Repository Example
- Details
- Written by Nam Ha Minh
- Last Updated on 28 February 2022   |   Print Email
When using Spring Data JPA, we used to declare a repository interface for a specific entity like this:
@Repository public interface ProductRepository extends JpaRepository<Product, Integer> { … }
This interface-based repository works for the queries that involve in a single entity that maps with a single in the database. What if we want to query data from multiple tables, and join cannot be used? In such case, we need to code a custom repository class that does not implement the interfaces JpaRepository or CrudRepository defined by Spring Data JPA.
1. When using Custom Repository?
Having said that, we will need to create a custom repository if using entity-bound repository interface does not work, or when we need to query data from multiple tables in which join cannot be used. In other words, use custom repository when we want to totally control the query code - not depending on the default semantics of Spring Data JPA’s repository interfaces.
Also using custom repository when you don’t want (or cannot) use the <Entity, ID> pair in the repository interface.
2. Spring Data JPA Custom Repository Code Example
Suppose that we have 3 entity classes Product, Customer and Order that map with the corresponding tables in database. Now we want to implement a REST API endpoint that returns some statistical information about the total numbers of product, customer and order:
package net.codejava.salesapp.api; @RestController public class SalesApi { @GetMapping("/api/statistic") public Statistic getStatistic() { // return statistical information... } }
The Statistic class is written as follows:
package net.codejava.salesapp.statistic; public class Statistic { private long productCount; private long customerCount; private long orderCount; // getters and setters are not shown for brevity }
So to query such statistical information from 3 tables product, customer and order, we will code a custom repository class and use EntityManger for executing 3 different Select Count queries, as follows:
package net.codejava.salesapp.statistic; import javax.persistence.*; import org.springframework.stereotype.Repository; @Repository public class StatisticRepository { @PersistenceContext private EntityManager entityManager; public Statistic getStatistic() { Statistic statistic = new Statistic(); Query query = entityManager.createQuery("Select count(p.id) FROM Product p"); long productCount = (Long) query.getSingleResult(); query = entityManager.createQuery("Select count(c.id) FROM Customer c"); long customerCount = (Long) query.getSingleResult(); query = entityManager.createQuery("Select count(o.id) FROM Order o"); long orderCount = (Long) query.getSingleResult(); statistic.setProductCount(productCount); statistic.setCustomerCount(customerCount); statistic.setOrderCount(orderCount); return statistic; } }
You see, this is an example of a custom repository class. We don’t create an interface extending JpaRepository or CrudRepository as usual with Spring Data JPA. Instead, we create a class annotated with @Repository and inject and instance of EntityManager with @PersistenceContext annotation.
Then we use the methods defined in the EntityManager interface to query the data in the way we want. This eliminates the limitation of the entity-bound repository interface.
In the service layer, code a service class as below:
@Service public class StatisticService { @Autowired private StatisticRepository repo; public Statistic getStatistic() { return repo.getStatistic(); } }
Then update code of the API endpoint controller class as follows:
@RestController public class SalesApi { @Autowired private StatisticService statsticService; @GetMapping("/api/statistic") public Statistic getStatistic() { return statsticService.getStatistic(); } }
So in a custom repository, you’re free to use the EntityManger’s methods to perform the queries (select or update) you need.
That’s an example of creating custom repository with Spring Data JPA. I recommend you watch the following video to see the coding in action:
Related Spring and Database Tutorials:
- Spring Data JPA EntityManager Examples (CRUD Operations)
- JPA EntityManager: Understand Differences between Persist and Merge
- Understand Spring Data JPA with Simple Example
- Spring Data JPA Native Query Examples
- Spring MVC with JdbcTemplate Example
- How to configure Spring MVC JdbcTemplate with JNDI Data Source in Tomcat
- Spring and Hibernate Integration Tutorial (XML Configuration)
- Spring MVC + Spring Data JPA + Hibernate - CRUD Example
Comments