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 JpaRepositoryor 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:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.
Comments