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

目录
  • 使用自定义repository实现原生sql
    • 自定义Repository接口
    • 创建自定义RepositoryFactoryBean
  • SpringDataJpa原生SQL查询
    • a.首先在StudentRepository里添加如下方法
    • b.在StudentController里面进行调用以上方法

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

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

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

(0)

相关推荐

  • 聊聊Spring data jpa @query使用原生SQl,需要注意的坑

    目录 Spring data jpa @Query 使用原生Sql的坑 根据代码来解说: 需要注意的方法有以下几点 SpringData JPA @Query动态SQL语句 思路 实现 Spring data jpa @Query 使用原生Sql的坑 根据代码来解说: @Query(value = "select bill.id_ as id, bill.created_date as date, bill.no, lawyer_case .case_no as caseNo, " +

  • 解决springdataJPA对原生sql支持的问题

    springdataJPA对原生sql支持问题 在项目中用到的是springdataJPA连接数据库进行操作,但是JPA中的hql语句不能够满足业务要求,因而需要用到原生sql 但是有一个问题: @Query(value = "SELECT ppd.* FROM zt_productionplandetails AS ppd \n" + " \tLEFT JOIN zt_salesplan sp ON sp.id=ppd.salesPlan_id \n" + &qu

  • Spring Data JPA使用JPQL与原生SQL进行查询的操作

    1.使用JPQL语句进行查询 JPQL语言(Java Persistence Query Language)是一种和SQL非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的SQL语言,从而屏蔽不同数据库的差异. JPQL语言通过Query接口封装执行,Query 接口封装了执行数据库查询的相关方法.调用 EntityManager 的 Query.NamedQuery 及 NativeQuery 方法可以获得查询对象,进而可调用Query接口的相关方法来执行查询操作. JPQ

  • Spring Data Jpa实现自定义repository转DTO

    近期项目中需要 关联 几张表再把字段转出来,在这里记录以下,我感觉网上写的都不太规范和清晰. @Entity @SqlResultSetMapping( name="TestMapping", entities = { @EntityResult( entityClass = com.xxx.xx.data.model.TestEntity.class, fields = { @FieldResult(name="id",column="id")

  • Spring Data JPA框架的Repository自定义实现详解

    目录 1. Spring Data Repository自定义实现 1.1 自定义特殊repository 1.2 配置类 1.3 解决歧义 1.4 手动装配 1.5 自定义Base Repository 1. Spring Data Repository自定义实现 Spring Data提供了各种选项来创建查询方法,只需少量编码.但是当这些选项不能满足你的需求时,你也可以为资源库方法提供你自己的自定义实现.本节主要介绍如何做到这一点. 1.1 自定义特殊repository 要用自定义的功能实

  • spring boot之使用spring data jpa的自定义sql方式

    目录 spring data jpa介绍 自定义SQL查询 jpa两种自定义SQL的方式 1. 原生SQL 2. 实体类SQL spring data jpa介绍 PA(Java Persistence API)是Sun官方提出的Java持久化规范.它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据.他的出现主要是为了简化现有的持久化开发工作和整合ORM技术,结束现在Hibernate,TopLink,JDO等ORM框架各自为营的局面.值得注意的是,JPA是在充分吸收

  • Spring Data Jpa返回自定义对象的3种方法实例

    目录 方法一.简单查询直接new对象 方法二.Service层使用EntityManager 方法三.Dao层使用Map接收自定义对象 总结 tasks表对应的Entity @Entity @NoArgsConstructor @AllArgsConstructor @Table(name = "tasks") @Data public class Tasks extends BaseEntity { @Id @GeneratedValue(strategy = GenerationT

  • Spring Data JPA映射自定义实体类操作

    目录 Spring Data JPA映射自定义实体类 JPA 配置类实体映射示例 Spring Data JPA映射自定义实体类 这个问题困扰了我2天=-=,好像也能使用 jpql解决 先说下自己的功能:查询oracle最近sql执行记录 sql很简单:[如果需要分页,需要自己手动分页,因为你使用分页工具他第一页查询不会查询rownum,第二页查询就会查询rownum,然而这个返回的List<Object[]>中的参数必须要和实体类中一一对应,所以这就有一个不可控制的属性rownum,所以我们

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

    目录 使用自定义repository实现原生sql 自定义Repository接口 创建自定义RepositoryFactoryBean SpringDataJpa原生SQL查询 a.首先在StudentRepository里添加如下方法 b.在StudentController里面进行调用以上方法 使用自定义repository实现原生sql Spring Data JPA中的Repository是接口,是JPA根据方法名帮我们自动生成的.但很多时候,我们需要为Repository提供一些自定

  • spring data jpa 查询自定义字段,转换为自定义实体方式

    目标:查询数据库中的字段,然后转换成 JSON 格式的数据,返回前台. 环境:idea 2016.3.4, jdk 1.8, mysql 5.6, spring-boot 1.5.2 背景:首先建立 entity 映射数据库(非专业 java 不知道这怎么说) @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long

  • spring data jpa如何使用自定义repository实现类

    目录 spring data jpa使用自定义repository实现类 创建MyJpaRepository实现类 创建MyJpaRepositoryFactoryBean 配置JPA JPA自定义 Repository 方法 包结构 类与接口之间的关系代码 经过实践发现 spring data jpa使用自定义repository实现类 spring data jpa中使用JpaRepository等接口定义repository时,将默认使用SimpleJpaRepository 可通过自定义

  • 详解Spring Data Jpa 模糊查询的正确用法

    模糊查询 Spring Data Jpa的使用可以减少开发者对sql语句的编写,甚至完全不需要编写sql语句.但是,开发过程中总会遇到各种复杂的场景以及大大小小的坑. 今天项目中某个功能模块需要用到模糊查询.原生sql中模糊查询关键字'Like',而Spring Data Jpa的Repository接口中恰恰也有实体字段对应的Like.但是,如果直接使用它,那么恭喜你,你幸运地掉坑了. Spring Data Jpa 模糊查询正确用法 首先,我们先创建一个实体用来存储我们的数据 /** * 实

  • Spring Data JPA中 in 条件参数的传递方式

    关于Spring Data JPA中自定义sql 条件的 in参数记录 此文做一个记录,以便以后观看,也希望正在遇到同样问题的同学能有所启发,如果你有更好的方法,或我的做法有问题,请告知下,非常感谢. 下面写两种简单做法,注意下地方: 在此我只记录HQL 中 in 后面参数问题,细节查询方法相关代码就略过,还请见谅 查询接口: /** ** paramString : 自定义 hql ** paramMap : hql中查询条件的参数 ** start:数据开始条数 ** max:最大数据条数

随机推荐