Spring Data JPA Custom Baserepository

Source: Internet
Author: User
Tags naming convention

At some special times, we will design a re-implementation of the methods in spring Data JPA, which will face a problem if we create a new implementation class. If the implementation class implements the Jparepository interface, so that we have to implement all the methods in the interface, and if we do not implement that interface, it means that we cannot use the useful methods provided by spring Data JPA. So in the extension we need to follow the following method.

It is important to note that the name of the interface and implementation class must follow spring data JPA's naming convention, if you want to write a custom interface for an interface StudentBaseRepository , you first need to create an interface name StudentBaseRepositoryCustom , which means a custom interface, the name of the implementation class must be StudentBaseRepositoryImpl , when StudentBaseRepository StudentBaseRepositoryCustom Once implemented, we can use our own method of implementation, as StudentBaseRepository well as inheriting JpaRepository to obtain the method that spring Data Jpa gives us.

The Studentbaserepositorycustom code is as follows

public interface StudentBaseRepositoryCustom {    //基于原生态的sql进行查询 List<Object[]> groupByStudentAsSql(); //基于Hibernate的HQL进行查询 List<Object[]> groupByStudentAsHql(); //基于Specification的方式进行查询,使用的是CriteriaQuery进行查询 List<Object[]> groupByStudentAsSpecification();}

The above code defines three methods, the first one is based on the original SQL to group query, the second is based on Hibernate hql query, the last one is to use the specification in the Criteriaquery to deal with, The first problem to solve is that Studentbaserepositorycustom does not implement repository, how to execute the SQL statement, we can inject another entitymanger to the implementation class, Execute the SQL statement through Entitymanager. The following is the implementation code for STUDENTBASEREPOSITORYIMPL

PublicClassStudentbaserepositoryimplImplementsStudentbaserepositorycustom {@Autowired@PersistenceContextPrivate Entitymanager Entitymanager;@OverridePublic list<object[]>Groupbystudentassql () {list<object[]> List = Entitymanager. Createnativequery ("Select Address,count (*) from t_student GROUP by Address"). Getresultlist ();return list; }@OverridePublic list<object[]>GROUPBYSTUDENTASHQL () {list<object[]> List = Entitymanager. CreateQuery ( "select Address,count (*) from Student GROUP by Address"). Getresultlist (); return list;}  @Override public list<object[]> groupbystudentasspecification () {//by address group query, and the number of students is greater than 3 of all addresses Criteriabuilder builder = Entitymanager.getcriteriabuilder (); criteriaquery<object[]> query = Builder.createquery (Object[].class); root<student> root = Query.from (Student.class); Query.multiselect (Root.get ( "id"))) . GroupBy (Root.get (3)); return entitymanager.createquery (query). Getresultlist ();}}      

The implementation of the previous two methods is very easy to understand, is to create a query statement, after execution will return a set of object[] projection, the third method is slightly more complex, this is the standard notation of criteriaquery.

Here we solve the problem of the extension class, but there are still some doubts, if each class has its own independent method, then not every class will have to follow the above aspects to write the interface and implementation class, although this can be a good solution to the extension of the custom class problem, but still a little more trouble, We can define a base class to cover some of the more common methods, such as generic SQL queries. Here we create this baserepository, the entire creation process is somewhat complex, you can refer to the source code of the project

Next we use the custom baserepository

The first step in creating defines an BaseRepository interface

/**
* General Repository
* We use it to simplify some of our repository's generic crud
* There is no need to write crud in every repository, just inherit it on the desired repository.
* @NoRepositoryBean, this indicates that the interface does not create an instance of this interface, such as Userinforepository,
* As long as the interface assembly in the base name configured in Jpaconfig is instantiated.
*/
@NoRepositoryBean
Public interface Baserepository<t,id extends serializable> extends jparepository<t,id>{
Custom SQL queries
list<t> listbysql (String sql);
Custom multi-condition dynamic query
List<t> Listbyown (map<string,object> map1,map<string,object> map2);
}
We then write the implementation classBaseRepositoryImpl
/**
* This implementation class comparison is simple, first we need to inherit simplejparepository,
* Simplejparepository helps us to implement the methods in Jparepository.
* Then implement the Baserepository interface. The Listbysql method is very simple, and the function is to execute a SQL return list of a set of projections.
* Created by BFD-593 on 2017/8/16.
*/
public class Baserepositoryimpl<t,id extends serializable> extends simplejparepository<t,id>
Implements baserepository<t,id>{
Private final Entitymanager Entitymanager;

The parent class does not have a constructor with no arguments, and the parent class is constructed here manually
Public Baserepositoryimpl (class<t> Domainclass,entitymanager entitymanager) {
Super (DomainClass, Entitymanager);
This.entitymanager = Entitymanager;
}
Complete the query through Entitymanager, specifying SQL to query
@Override
Public list<t> listbysql (String sql) {
return entitymanager.createnativequery (SQL). Getresultlist ();
}

@Override
Public list<t> Listbyown (final map<string,object> map1, final map<string,object> map2) {
specification<t> SF = new Specification<t> () {
@Override
Public predicate topredicate (root<t> Root, criteriaquery<?> criteriaquery, Criteriabuilder Criteriabuilder) {
list<predicate> list = new arraylist<> ();
String key1 = (string) map1.keyset (). ToArray () [0];
String key2 = (string) map2.keyset (). ToArray () [0];
if (Stringutils.isnotempty (Key1)) {
List.add (Criteriabuilder.like (Root.get (Key1). As (String.class), "%" +map1.get (key1) + "%"));
}
if (Stringutils.isnotempty (Key2)) {
List.add (Criteriabuilder.greaterthanorequalto (Root.get (Key2). As (Integer.class), (Integer) Map2.get (Key2)));
}
Predicate[] Pre = new predicate[list.size ()];
Criteriaquery.where (List.toarray (pre));
return Criteriaquery.getrestriction ();
}
};
Return FindAll (SF);
}
}
Next we need to create a custom factory that registers the implementation of our own defined Baserepositoryimpl in this factory.
/**
* We need to create a custom factory,
* Register the implementation of our own defined Baserepositoryimpl in this factory.
* This factory is written in reference to spring Data's Jparepositoryfactorybean and jparepositoryfactory.
* This class above a bunch of generics, we don't have to consider, just follow the same way to write.
* Created by BFD-593 on 2017/8/16.
*/
public class Baserepositoryfactorybean<r extends Jparepository<t, I>, T,
I extends serializable> extends Jparepositoryfactorybean<r, T, i> {
Public Baserepositoryfactorybean (class<? extends r> Repositoryinterface) {
Super (Repositoryinterface);
}

/**
* This method is in Jparepositoryfactorybean,
* The purpose is to return a factory, we call it back to our own factory
* @param Entitymanager
* @return
*/
@Override
Protected Repositoryfactorysupport createrepositoryfactory (Entitymanager entitymanager) {
return new Baserepositoryfactory (Entitymanager);
}
Create an inner class that does not have to be accessed externally
private static class Baserepositoryfactory<t,i extends Serializable> extends jparepositoryfactory{
Private final Entitymanager Entitymanager;
Public baserepositoryfactory (Entitymanager Entitymanager) {
Super (Entitymanager);
This.entitymanager=entitymanager;
}

/**
* Using these two methods to determine the specific implementation class, the method in Jparepositoryfactory
* This is the implementation class that will be created when spring Data JPA instantiates an interface specifically.
* Spring Data JPA calls Simplejparepository to create an instance. The following is the code of our own factory implementation
* @param information
* @return
*/
Setting the specific implementation class is Baserepositoryimpl
@Override
Protected Object gettargetrepository (repositoryinformation information) {
return new Baserepositoryimpl<t, i> ((class<t>) Information.getdomaintype (), Entitymanager);
}
Set the class of the specific implementation classes
@Override
Protected class<?> Getrepositorybaseclass (Repositorymetadata metadata) {
return baserepositoryimpl.class;
}
}
}

Then we need to get spring to find our custom baserepository factory when it loads, and when we use springboot, everything becomes simple, just add it in the entry class @EnableJpaRepositories , the code is as follows


/**
* When we use universal repository
* We need to get spring to find our custom Baserepositoryfactorybean factory at load time,
* As long as you add @enablejparepositories to the entry class, the code is as follows
*/
@EnableJpaRepositories (basepackages = {"Com.example.demo.dao"},
Repositoryfactorybeanclass = Baserepositoryfactorybean.class)//Our own factory
@SpringBootApplication
public class Springbootjpaapplication {
public static void Main (string[] args) {
Springapplication.run (Springbootjpaapplication.class, args);
}
}
The process of our entire custom factory here is over, and we write an interface implementation BaseRepository .
Specific code please see Https://github.com/peterowang/spring-data-jpa-demo

Spring Data JPA Custom Baserepository

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.