SpringDataJPA是Spring Data的一个子项目,经过提供基于JPA的Repository极大的减小了JPA做为数据访问方案的代码量,你仅仅须要编写一个接口集成下SpringDataJPA内部定义的接口便可完成简单的CRUD操做,理论的东西不作多解释,下面咱们开始讲解SpringBootgit
咱们使用IntelliJ IDEA工具构建一个SpringBoot项目,预先导入Web、MySQL、JPA依赖,咱们简单使用一个RestController来实现JPA的配置,以前也有讲解JPA的简单使用,今天详细的讲解下具体的细节性的内容,项目结构以下图1所示:spring
咱们使用以前章节的配置,加入Druid数据源配置到咱们的项目中,复制第四章:使用Druid做为SpringBoot项目数据源(添加监控)项目中的application.yml配置文件到咱们项目resources下,而且修改pom.xml添加Druid数据源依赖,以下图2所示:sql
application.yml配置文件内容以下图3所示(具体代码请到码云下载地址:git.oschina.net/jnyqy/lesso…):数据库
咱们在配置使用JpaRepository以前须要对应咱们的测试表添加实体映射,为了本章的方便咱们直接使用第四章:使用Druid做为SpringBoot项目数据源(添加监控)内的表结构以及实体,sql文件在第四章项目源码的resource目录下,能够下载后自行加载到本地数据库中,表结构以下图4所示:tomcat
根据表结构建立对应的实体映射,简单点,咱们使用单表操做,SpringDataJPA与Hibernate的语法一致内部都是使用了JPA的实现。映射实体代码以下图5所示:架构
上述图5的getter/setter方法我没有贴出来,自行工具构建就能够了。咱们的准备作好了,下面咱们建立UserJPA接口,上图5我已经建立到了jpa目录内,建立完成后打开添加继承自JpaRepository,JpaRepository须要泛型接口参数,第一个参数是实体,第二则是主键的类型,UserJPA代码以下图6所示:app
数据访问的接口就算是实现了,咱们继承的JpaRepository接口内有又继承了PagingAndSortingRepository接口以及QueryByExampleExecutor接口,这两个接口是用来干什么的?而PagingAndSortingRepository接口内部又有一个继承自CrudRepository接口。若是对架构有点了解的朋友应该都知道,这样设计得好处。框架
该接口内包含了最简单的CRUD也就是Create、Read、Update、Delete方法,固然还有count、exists方法,以下图7所示:less
若是自行定义的JPA继承了该接口就会拥有CrudRepository接口内的全部方法实现。spring-boot
该接口继承自CrudRepository接口,包含了最基本的CRUD方法的实现,该接口内部添加了两个方法,以下图8所示:
顾名思义,看到接口名称就能够联想了,这个方法就是为了分页而设计的,固然不只仅是分页还有排序方法。
咱们的JpaRepository接口继承了该接口,这个接口提供条件查询,复杂查询方法,能够经过Example方式进行查询数据,源码以下图9所示:
后面咱们会讲到QueryDSL,到那时你就会知道SpringDataJPA提供的复杂条件查询并非最好的选择。
咱们自定义的接口继承了它,也就是说咱们的UserJPA拥有了JpaRepository接口及父类接口的全部方法实现,因此咱们并不须要添加任何数据操做代码就能够完成数据操做,JpaRepository接口对条件查询以及保存集合数据添加了对应的方法,代码以下图10所示:
具体每一个方法是用来作什么的,根据名称就能够看到,这里就不作一一的讲解了。下面咱们须要测试咱们建立的UserJPA是否能够完成咱们上述说的数据操做。
咱们直接在controller包下建立一个UserController控制器,添加@RestController注解支持,咱们由于方便这里就不编写Service层的代码实现了,直接在Controller内注入UserJPA,代码以下图11所示:
咱们在UserController内添加了JpaRepository内部实现的findAll方法,用来查询所有用户数据,下面咱们启动项目测试。
当你使用SpringBootApplication方式运行项目时控制台会输出项目运行失败的日志提示,这里咱们须要注释掉spring-boot-starter-tomcat依赖的scope属性就能够了。
尝试访问用户列表地址:127.0.0.1:8080/list,能够看到页面输出了一条数据,这条数据是我事先在数据库中手动添加的,以下图12所示:
咱们编写简单的添加数据方法在UserController内,代码以下图13所示:
咱们在add方法内建立了一个UserEntity对象并对全部的字段都赋值。
注意:SpringDataJPA内有个save方法,这个方法不只仅是用来添加数据使用,当咱们传入主键的值时则是根据主键的值完成更新数据操做。
咱们重启下项目,尝试访问127.0.0.1:8080/add地址,界面输出内容以下图14所示:
界面给了咱们数据添加成功的提示,咱们访问list地址验证是否已经添加成功,以下图15所示:
能够看到,数据已经经过add方法添加到数据库内。因为更新的操做与添加一致这里就不作讲解了,你只须要传入主键的值便可。
咱们简单实现删除一条数据,在UserController内添加delete方法,方法接受一个主键参数,以下图16所示:
当咱们访问/delete时传入userId参数就能够删除对应的数据,下面咱们重启下项目,访问127.0.0.1:8080/delete?userId=5,界面输入内容以下图17所示:
数据已经成功的完成了删除操做。
上面的操做一切都是SpringDataJPA为咱们自动完成的,到目前为止咱们并无编写一句SQL,那么SpringDataJPA是否支持自定义SQL语句呢?答案必须是确定的!由于它是这个的强大!
SpringDataJPA内部有两种方式能够实现自定义SQL功能,咱们先来说述使用注解的方式,后期在SpringDataJPA核心技术专题内再详细的讲解使用EntityManager是如何完成自定义SQL、调用存储过程、视图等等操做的。下面咱们打开UserJPA接口,添加自定义查询年龄大于20的数据,以下图18所示:
@Query是用来配置自定义SQL的注解,后面参数nativeQuery = true才是代表了使用原生的sql,若是不配置,默认是false,则使用HQL查询方式。咱们在UserController内添加方法/age,测试咱们的自定义SQL是否有效,代码以下图19所示:
重启下项目,访问127.0.0.1:8080/age,效果以下图20所示:
从名字上能够看到咱们的@Query注解好像只是用来查询的,可是若是配合@Modifying注解一共使用,则能够完成数据的删除、添加、更新操做。下面咱们来测试下自定义SQL完成删除数据的操做,我根据名字、密码字段共同删除一个数据,接口代码以下图21所示:
咱们再来编写UserController添加对应的方法调用deleteQuery接口方法,以下图22所示:
重启下项目,访问地址:127.0.0.1:8080/deleteWhere,界面输出内容以下图23所示:
界面居然出现了异常,这是怎么回事呢?能够看到抛出的异常TranscationRequiredException,意思就是你当前的操做给你抛出了须要事务异常,SpringDataJPA自定义SQL时须要在对应的接口或者调用接口的地方添加事务注解@Transactional,来开启事务自动化管理。下面咱们在UserJPA内添加@Transactional注解,重启项目再来访问刚才的地址,效果以下图24所示:
界面已经给我提示了删除成功,咱们查看下控制台看打印的SQL是不是咱们自定义的,以下图25所示:
咱们自定义的SQL被成功的打印了,自定义SQL完成添加,更新操做时跟删除一致,都须要添加@Query以及@Modifying注解配合使用。
项目在正常状况下不只仅只继承一个JpaRepository接口,下一章咱们整合SpringDataJPA跟QueryDSL时就须要添加多个接口继承了,那么咱们业务数据接口每个都去继承几个相同的接口?答案确定是 NO,固然多个继承也是能够的,不过对于系统设计还有代码复用性来讲并非最好的选择!
咱们建立一个包名叫作base,在包内添加一个BaseRepository接口,而且接口继承咱们的JpaRepository,代码以下图26所示:
又出现了一个新的注解,@NoRepositoryBean,这个注解是用来干什么的呢?
Spring开源程序猿在命名规则上应该是比较严格的,从名字上咱们几乎就能够判断出用途,这个注解若是配置在继承了JpaRepository接口以及其余SpringDataJpa内部的接口的子接口时,子接口不被做为一个Repository建立代理实现类。
咱们建立的业务数据接口直接继承BaseRepository就好了,继承的子接口会拥有JpaRepository全部方法实现。
分页对于大型系统来讲确定是必不可少的,那么咱们在SpringDataJpa内是如何使用分页来完成查询的呢?
通常状况咱们会建立一个BaseEntity,在BaseEntity内添加几个字段:排序列,排序方式,当前页码,每页条数等,下面咱们也来建立这么一个父类,代码以下图27所示:
咱们修改UserEntity继承BaseEntity,而后在数据库内添加上几条测试数据,咱们每次页面的数量就不用20了,咱们在建立查询条件时修改为2条。
咱们打开UserController添加cutPage方法,用于做为分页查询入口,(注意:文章的讲解都没有添加Service层因此全部的业务逻辑都在Controller内处理的,正式项目请不要这样编写。)咱们在cutPage方法内添加对应的分页逻辑,以下图28所示:
接下来咱们重启下项目,访问地址:127.0.0.1:8080/cutpage?page=1,查看界面输出效果以下图29所示:
咱们再来看下控制台的输出,以下图30所示:
能够看到控制台给咱们打印了两条SQL,第一条是分页查询的SQL,第二条是查询表内总数量的SQL。SpringDataJPA内部对数量作出了封装,你能够经过Page对象也就是PagingAndSortingRepository接口内的findAll(PageRequest request)方法的返回值类型中获取到总条数、总页数。
咱们上面在BaseEntity内添加了排序的字段以及排序方式,咱们从新编辑下cutPage方法,修改pageRequest建立方式,添加Sort对象到PageRequest对象内,就能够实现排序数据。以下图31所示:
上图31能够看到咱们修改了排序字段咱们使用了默认的id,(注意:这里的排序字段不是数据库内的字段名而是实体内的属性名)以及排序方式改为了倒序,SpringDataJPA对排序方式添加了一个枚举类型,建立Sort对象时也须要枚举对象,由于咱们BaseEntity配置的是字符串因此上面多了一步判断排序方式返回枚举对象。
重启下项目,再来访问分页路径,界面输出效果以下图32所示:
能够看到数据已是倒序方式展现了,控制台的日志输出也对应的添加了order by语句,以下图33所示:
综上所述本章的内容已经讲解完了,本章的内容比较多昨天完成没有编写完,还请见谅。本章主要讲解了SpringBoot项目中使用SpringDataJPA的基本操做,包括了:CURD、分页、排序、自定义SQL、定义BaseRepository、事务处理等。本章内容并非SpringDataJPA全面内容,后续我会在SpringDataJPA核心技术专题详细讲解。
本章内容已经更新到码云:
SpringBoot配套源码地址:gitee.com/hengboy/spr…
SpringCloud配套源码地址:gitee.com/hengboy/spr…
SpringBoot相关系列文章请访问:目录:SpringBoot学习目录
QueryDSL相关系列文章请访问:QueryDSL通用查询框架学习目录
SpringDataJPA相关系列文章请访问:目录:SpringDataJPA学习目录
SpringBoot相关文章请访问:目录:SpringBoot学习目录,感谢阅读!
欢迎加入QQ技术交流群,共同进步。