简体   繁体   中英

Spring Data JPA: Implementing Custom Repository Behavior with Specifications

I would like to create a Spring Data JPA repository with custom behavior, and implement that custom behavior using Specification s. I have gone through the Spring Data JPA documentation for implementing custom behavior in a single repository to set this up, except there is no example of using a Spring Data Specification from within a custom repository. How would one do this, if even possible?

I do not see a way to inject something into the custom implementation that takes a specification. I thought I would be tricky and inject the CRUD repository portion of the repository into the custom portion, but that results in a circular instantiation dependency.

I am not using QueryDSL. Thanks.

I guess the primary source for inspiration could be how SimpleJpaRepository handles specifications. The key spots to have a look at are:

  • SimpleJpaRepository.getQuery(…) - it's basically creating a CriteriaQuery and bootstraps a select using a JPA Root . Whether the latter applies to your use case is already up to you. I think the former will apply definitely.
  • SimpleJpaRepository.applySpecificationToCriteria(…) - it basically uses the artifacts produced in getQuery(…) (ie the Root and the CriteriaQuery ) and applies the given Specification to exactly these artifacts.

this is not using Specification, so not sure if it's relevant to you, but one way that I was able to inject custom behavior is as follows,

  1. Basic structure: as follows

    i. create a generic interface for the set of entity classes which are modeled after a generic parent entity. Note, this is optional. In my case I had a need for this hierarchy, but it's not necessary

     public interface GenericRepository<T> { // add any common methods to your entity hierarchy objects, // so that you don't have to repeat them in each of the children entities // since you will be extending from this interface } 

    ii. Extend a specific repository from generic (step 1) and JPARepository as

     public interface MySpecificEntityRepository extends GenericRepository<MySpecificEntity>, JpaRepository<MySpecificEntity, Long> { // add all methods based on column names, entity graphs or JPQL that you would like to // have here in addition to what's offered by JpaRepository } 

    iii. Use the above repository in your service implementation class

    1. Now, the Service class may look like this,

       public interface GenericService<T extends GenericEntity, ID extends Serializable> { // add specific methods you want to extend to user } 
    2. The generic implementation class can be as follows,

       public abstract class GenericServiceImpl<T extends GenericEntity, J extends JpaRepository<T, Long> & GenericRepository<T>> implements GenericService<T, Long> { // constructor takes in specific repository public GenericServiceImpl(J genericRepository) { // save this to local var } // using the above repository, specific methods are programmed } 
    3. specific implementation class can be

       public class MySpecificEntityServiceImpl extends GenericServiceImpl<MySpecificEntity, MySpecificEntityRepository> implements MySpecificEntityService { // the specific repository is autowired @Autowired public MySpecificEntityServiceImpl(MySpecificEntityRepository genericRepository) { super(genericRepository); this.genericRepository = (MySpecificEntityRepository) genericRepository; } } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM