欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

spring-data-jpa使用自定义repository来实现原生sql

程序员文章站 2022-06-25 09:54:58
目录使用自定义repository实现原生sql自定义repository接口创建自定义repositoryfactorybeanspringdatajpa原生sql查询a.首先在studentrep...

使用自定义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; 
}

运行效果请各位自行测试。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。