spring-data-jpa使用自定义repository来实现原生sql
使用自定义repository实现原生sql
spring data jpa中的repository是接口,是jpa根据方法名帮我们自动生成的。但很多时候,我们需要为repository提供一些自定义的实现。今天我们看看如何为repository添加自定义的方法。
自定义repository接口
首先我们来添加一个自定义的接口:
- 添加baserepository接口
- baserepository继承了jparepository,这样可以保证所有repository都有jpa提供的基本方法。
- 在baserepository上添加@norepositorybean标注,这样spring data jpa在启动时就不会去实例化baserepository这个接口
/** * created by liangkun on 2016/12/7. */ @norepositorybean public interface baserepository<t,id extends serializable> extends jparepository<t,id> { //sql原生查询 list<map<string, object>> listbysql(string sql); }
接下来实现baserepository接口,并继承simplejparepository类,使其拥有jpa repository的提供的方法实现。
/** * created by liangkun on 2017/12/7. */ public class baserepositoryimpl<t, id extends serializable> extends simplejparepository<t,id> implements baserepository<t,id> { private final entitymanager entitymanager; //父类没有不带参数的构造方法,这里手动构造父类 public baserepositoryimpl(class<t> domainclass, entitymanager entitymanager) { super(domainclass, entitymanager); this.entitymanager = entitymanager; } //通过entitymanager来完成查询 @override public list<map<string, object>> listbysql(string sql) { return entitymanager.createnativequery(sql).getresultlist(); } }
这里着重说下entitymanager
entitymanager是jpa中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的java对象和数据库的数据存储。也可以根据他进行sql的原生查找。
源码如下:
public interface entitymanager { <t> t find(class<t> var1, object var2); query createnativequery(string var1); query createnativequery(string var1, class var2); query createnativequery(string var1, string var2); }
由上可以看出其有具体的原生查询实现接口 createnativequery
接下来需要将我们自定义的repository接口,通过工厂模式添加到spring的容器中:
创建自定义repositoryfactorybean
接下来我们来创建一个自定义的repositoryfactorybean来代替默认的repositoryfactorybean。repositoryfactorybean负责返回一个repositoryfactory,spring data jpa 将使用repositoryfactory来创建repository具体实现。
查看jparepositoryfactorybean的源码,通过createrepositoryfactory返回jparepositoryfactory实例:
public class jparepositoryfactorybean<t extends repository<s, id>, s, id extends serializable> extends transactionalrepositoryfactorybeansupport<t, s, id> { private entitymanager entitymanager; public jparepositoryfactorybean(class<? extends t> repositoryinterface) { super(repositoryinterface); } @persistencecontext public void setentitymanager(entitymanager entitymanager) { this.entitymanager = entitymanager; } @override public void setmappingcontext(mappingcontext<?, ?> mappingcontext) { super.setmappingcontext(mappingcontext); } @override protected repositoryfactorysupport docreaterepositoryfactory() { return createrepositoryfactory(entitymanager); } protected repositoryfactorysupport createrepositoryfactory(entitymanager entitymanager) { return new jparepositoryfactory(entitymanager); } @override public void afterpropertiesset() { assert.notnull(entitymanager, "entitymanager must not be null!"); super.afterpropertiesset(); } }
终上我们可根据相应的规则进行创建自定义repositoryfactorybean
/** * created by liangkun on 2018/07/20. */ 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); } @override protected repositoryfactorysupport createrepositoryfactory(entitymanager em) { return new baserepositoryfactory(em); } //创建一个内部类,该类不用在外部访问 private static class baserepositoryfactory<t, i extends serializable> extends jparepositoryfactory { private final entitymanager em; public baserepositoryfactory(entitymanager em) { super(em); this.em = em; } //设置具体的实现类是baserepositoryimpl @override protected object gettargetrepository(repositoryinformation information) { return new baserepositoryimpl<t, i>((class<t>) information.getdomaintype(), em); } //设置具体的实现类的class @override protected class<?> getrepositorybaseclass(repositorymetadata metadata) { return baserepositoryimpl.class; } } }
自定义完成。
springdatajpa原生sql查询
一些比较复杂的关联查询要怎么实现呢,jpa的处理方法是:利用原生的sql命令来实现那些复杂的关联查询,通过设置nativequery = true 来设置开启使用数据库原生sql语句。下面就在上一个案例的基础上实现原生sql的增删改查,代码如下。
a.首先在studentrepository里添加如下方法
//利用原生的sql进行查询操作 @query(value = "select s.* from studenttb s where s.student_name=?1", nativequery = true) public list<student> findstudentbyname(string name); //利用原生的sql进行删除操作 @query(value = "delete from studenttb where student_id=?1 ", nativequery = true) @modifying @transactional public int deletestudentbyid(int uid); //利用原生的sql进行修改操作 @query(value = "update studenttb set student_name=?1 where student_id=?2 ", nativequery = true) @modifying @transactional public int updatestudentname(string name,int id); //利用原生的sql进行插入操作 @query(value = "insert into studenttb(student_name,student_age) value(?1,?2)", nativequery = true) @modifying @transactional public int insertstudent(string name,int age); @query(value=" select * from studenttb where student_name like %:name% ",nativequery=true) list<student> querybynamesql(@param(value = "name") string name);
b.在studentcontroller里面进行调用以上方法
代码如下:
//原生sql的调用 /*** * http://localhost:8090/findstudentbyname?name=刘一 * @param name * @return */ @requestmapping("/findstudentbyname") public object findstubyname(string name) { list<student> student = repository.findstudentbyname(name); return student; } /*** * http://localhost:8090/deletestudentbyid?id=刘 * @param name * @return */ @requestmapping("/deletestudentbyid") public object deletestudentbyid(int id) { int i = repository.deletestudentbyid(id); map<string,object> map=new hashmap<string,object>(); if(i>0) { map.put("success", true); } else { map.put("success", false); } return map; } /*** * http://localhost:8090/updatestudentname?name=tom&id=1 * @param name * @return */ @requestmapping("/updatestudentname") public object updatestudentname(string name,int id) { int i = repository.updatestudentname(name,id); map<string,object> map=new hashmap<string,object>(); if(i>0) { map.put("success", true); } else { map.put("success", false); } return map; } /*** * http://localhost:8090/insertstudent?name=xiao&age=18 * @param name * @return */ @requestmapping("/insertstudent") public object insertstudent(string name,int age) { int i = repository.insertstudent(name,age); map<string,object> map=new hashmap<string,object>(); if(i>0) { map.put("success", true); } else { map.put("success", false); } return map; } /*** * http://localhost:8090/querybynamesql?name=刘 * @param name * @return */ @requestmapping("/querybynamesql") public object querybynamesql(string name) { list<student> student= repository.querybynamesql(name); return student; }
运行效果请各位自行测试。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
上一篇: 简单易懂理解事务的隔离级别
下一篇: vue单文件组件的实现