@NoRepositoryBean: Spring Data JPA does not instantiate this interface when it is started BaseRepository
1. Common interface:
Import org.springframework.data.jpa.repository.JpaRepository; Import Org.springframework.data.jpa.repository.JpaSpecificationExecutor; Import Org.springframework.data.repository.NoRepositoryBean; /** * Generic DAO interface * */ @NoRepositoryBean Public Interface extends Jparepository<t, Long>, jpaspecificationexecutor<t> { }
2. Adding a custom method: 2.1 Customizing the Repository interface
@NoRepositoryBean Public Interface extends Serializable> extends pagingandsortingrepository<t, id> { boolean Support (String modeltype);}
- Add
BaseRepository
interface
BaseRepository
Inherited PagingAndSortingRepository
, this can ensure that all repository have basic additions and deletions and other methods such as paging.
BaseRepository
add annotations on @NoRepositoryBean
, so that spring Data JPA does not instantiate BaseRepository
this interface at startup
- Adds a
support(String modelType)
method that indicates whether the domain object of the repository is a modelType
type
2.2 Implementing the Baserepository interface
Public classBaserepositoryimpl<t, IDextendsSerializable>extendsSimplejparepository<t, id>ImplementsBaserepository<t, id> { Private FinalClass<t>DomainClass; PublicBaserepositoryimpl (class<t>DomainClass, Entitymanager Entitymanager) { Super(DomainClass, Entitymanager); This. DomainClass =DomainClass; } @Override Public BooleanSupport (String modeltype) {returndomainclass.getname (). Equals (Modeltype); }}
After defining a custom method, we now implement the method with a basic repository class:
First add the Baserepositoryimpl class and inherit the Simplejparepository class, which has the basic method of JPA repository.
We found that repository has two constructors:
- Simplejparepository (jpaentityinformation entityinformation, Entitymanager Entitymanager)
- Simplejparepository (Class domainclass, Entitymanager em)
Here we implement the second constructor, get domainClass
and EntityManager
two objects. Because what we want to do is to know whether a repository supports the type of a domain object, so we keep the information when we implement the constructor domainClass
.
The last implementation support
method, whose parameters are the type of the domain object, compares it and contrasts it, and if it is domainClass
equal, the repository supports the realm object of that type:
2.3 Creating a custom Repositoryfactorybean
Next, let's create a custom RepositoryFactoryBean
to replace the default RepositoryFactoryBean
. RepositoryFactoryBean
responsible for returning a RepositoryFactory
, Spring Data Jpa will be used RepositoryFactory
to create the repository concrete implementation, where we use BaseRepositoryImpl
instead SimpleJpaRepository
as an implementation of the Repository interface. This allows us to achieve the purpose of adding custom methods for all repository.
Public classBaserepositoryfactorybean<rextendsJparepository<t, I>, T, IextendsSerializable>extendsJparepositoryfactorybean<r, T, i>{@Overrideprotectedrepositoryfactorysupport createrepositoryfactory (Entitymanager em) {return Newmyrepositoryfactory (EM); } Private Static classMyrepositoryfactory<t, IextendsSerializable>extendsJparepositoryfactory {Private FinalEntitymanager em; Publicmyrepositoryfactory (Entitymanager em) {Super(EM); This. Em =em; } @OverrideprotectedObject gettargetrepository (Repositorymetadata metadata) {return NewBaserepositoryimpl<t, I> (class<t>) Metadata.getdomaintype (), EM); } @OverrideprotectedClass<?>getrepositorybaseclass (Repositorymetadata metadata) {returnBaserepositoryimpl.class; } }}
2.4 Configuring the JPA factory class
Finally, we need to configure JPA to use our custom BaseRepositoryFactoryBean
. Spring supports the use of annotations for configuration, and we com.tmy.App
add annotations in @EnableJpaRepositories(repositoryFactoryBeanClass = BaseRepositoryFactoryBean.class)
:
= Baserepositoryfactorybean. class publicclass App { publicstaticvoid Main ( String[] args) { springapplication.run (App.class, args);} }
This allows us to add a custom method to all repository.
2.5 Testing
We have added one TestController
for testing. Go to the root directory and execute mvn spring-boot:run
it to run our app.
After the app launches, separate access http://localhost:8080/test?type=blog&id=1
and http://localhost:8080/test?type=article&id=1
, we'll see article and blog two different objects.
In TestController
, we get a list of all repository through dependency injection. When the user accesses /test
, the system will find the type
corresponding repository according to the traversal of all repository, and then call the method to find the findOne(id)
corresponding object. So we don't need one. To get repository instances, this is a more efficient way to manage objects when the domain objects become more and more powerful.
@RestController Public classTestController {@AutowiredPrivateList<baserepository>repositories; @RequestMapping (Value= "/test", method=requestmethod.get) PublicObject getentry (@RequestParam (value= "type", required =true) String type, @RequestParam (value= "id", required=true) (Integer ID) {if(Type.equals ("article") ) {type= article.class. GetName (); }Else if(Type.equals ("blog") ) {type= Blog.class. GetName (); } for(Baserepository baserepository:repositories) {if(Baserepository.support (type)) {returnBaserepository.findone (ID); } } return NULL; }}
Reference:
Https://www.tianmaying.com/tutorial/spring-jpa-custom-all
Vii. Springboot Integration of SPRING-DATA-JPA (II.) Generic DAO interface and adding custom methods