zoukankan      html  css  js  c++  java
  • SpringBoot实战SpringDataJPA

    SpringDataJPASpring Data的一个子项目,通过提供基于JPARepository极大的减少了JPA作为数据访问方案的代码量,你仅仅需要编写一个接口集成下SpringDataJPA内部定义的接口即可完成简单的CRUD操作,理论的东西不做多解释,下面我们开始讲解SpringBoot

    构建项目

    我们使用IntelliJ IDEA工具构建一个SpringBoot项目,预先导入Web、MySQL、JPA依赖,我们简单使用一个RestController来实现JPA的配置,之前也有讲解JPA的简单使用,今天详细的讲解下具体的细节性的内容,项目结构如下图1所示:

     
    图1

    使用Druid数据源

    我们使用之前章节的配置,加入Druid数据源配置到我们的项目中,复制第四章:使用Druid作为SpringBoot项目数据源(添加监控)项目中的application.yml配置文件到我们项目resources下,并且修改pom.xml添加Druid数据源依赖,如下图2所示:

     
    图2

    application.yml配置文件内容如下图3所示(具体代码请到码云下载地址:git.oschina.net/jnyqy/lessons):

     
    图3

    使用JpaRepository

    我们在配置使用JpaRepository之前需要对应我们的测试表添加实体映射,为了本章的方便我们直接使用第四章:使用Druid作为SpringBoot项目数据源(添加监控)内的表结构以及实体,sql文件在第四章项目源码的resource目录下,可以下载后自行加载到本地数据库中,表结构如下图4所示:

     
    图4

    根据表结构创建对应的实体映射,简单点,我们使用单表操作,SpringDataJPAHibernate的语法一致内部都是使用了JPA的实现。映射实体代码如下图5所示:

     
    图5

    上述图5的getter/setter方法我没有贴出来,自行工具构建就可以了。我们的准备做好了,下面我们创建UserJPA接口,上图5我已经创建到了jpa目录内,创建完成后打开添加继承自JpaRepositoryJpaRepository需要泛型接口参数,第一个参数是实体,第二则是主键的类型,UserJPA代码如下图6所示:

     
    图6

    数据访问的接口就算是实现了,我们继承的JpaRepository接口内有又继承了PagingAndSortingRepository接口以及QueryByExampleExecutor接口,这两个接口是用来干什么的?而PagingAndSortingRepository接口内部又有一个继承自CrudRepository接口。如果对架构有点了解的朋友应该都知道,这样设计得好处。

    CrudRepository

    该接口内包含了最简单的CRUD也就是Create、Read、Update、Delete方法,当然还有count、exists方法,如下图7所示:

     
    图7

    如果自行定义的JPA继承了该接口就会拥有CrudRepository接口内的所有方法实现。

    PagingAndSortingRepository

    该接口继承自CrudRepository接口,包含了最基本的CRUD方法的实现,该接口内部添加了两个方法,如下图8所示:

     
    图8

    顾名思义,看到接口名称就可以联想了,这个方法就是为了分页而设计的,当然不仅仅是分页还有排序方法。

    QueryByExampleExecutor

    我们的JpaRepository接口继承了该接口,这个接口提供条件查询,复杂查询方法,可以通过Example方式进行查询数据,源码如下图9所示:

     
    图9

    后面我们会讲到QueryDSL,到那时你就会知道SpringDataJPA提供的复杂条件查询并不是最好的选择。

    JpaRepository

    我们自定义的接口继承了它,也就是说我们的UserJPA拥有了JpaRepository接口及父类接口的所有方法实现,所以我们并不需要添加任何数据操作代码就可以完成数据操作,JpaRepository接口对条件查询以及保存集合数据添加了对应的方法,代码如下图10所示:

     
    图10

    具体每个方法是用来做什么的,根据名称就可以看到,这里就不做一一的讲解了。下面我们需要测试我们创建的UserJPA是否可以完成我们上述说的数据操作。

    创建测试控制器

    我们直接在controller包下创建一个UserController控制器,添加@RestController注解支持,我们因为方便这里就不编写Service层的代码实现了,直接在Controller内注入UserJPA,代码如下图11所示:

     
    图11

    我们在UserController内添加了JpaRepository内部实现的findAll方法,用来查询全部用户数据,下面我们启动项目测试。

    初尝试运行测试

    当你使用SpringBootApplication方式运行项目时控制台会输出项目运行失败的日志提示,这里我们需要注释掉spring-boot-starter-tomcat依赖的scope属性就可以了。

    查询数据

    尝试访问用户列表地址:127.0.0.1:8080/list,可以看到页面输出了一条数据,这条数据是我事先在数据库中手动添加的,如下图12所示:

     
    图12

    添加数据

    我们编写简单的添加数据方法在UserController内,代码如下图13所示:

     
    图13

    我们在add方法内创建了一个UserEntity对象并对所有的字段都赋值。

    注意:SpringDataJPA内有个save方法,这个方法不仅仅是用来添加数据使用,当我们传入主键的值时则是根据主键的值完成更新数据操作。

    我们重启下项目,尝试访问127.0.0.1:8080/add地址,界面输出内容如下图14所示:

     
    图14

    界面给了我们数据添加成功的提示,我们访问list地址验证是否已经添加成功,如下图15所示:

     
    图15

    可以看到,数据已经通过add方法添加到数据库内。由于更新的操作与添加一致这里就不做讲解了,你只需要传入主键的值即可。

    删除数据

    我们简单实现删除一条数据,在UserController内添加delete方法,方法接受一个主键参数,如下图16所示:

     
    图16

    当我们访问/delete时传入userId参数就可以删除对应的数据,下面我们重启下项目,访问127.0.0.1:8080/delete?userId=5,界面输入内容如下图17所示:

     
    图17

    数据已经成功的完成了删除操作。

    上面的操作一切都是SpringDataJPA为我们自动完成的,到目前为止我们并没有编写一句SQL,那么SpringDataJPA是否支持自定义SQL语句呢?答案必须是肯定的!因为它是这个的强大!

    @Query注解自定义SQL

    SpringDataJPA内部有两种方式可以实现自定义SQL功能,我们先来讲述使用注解的方式,后期在SpringDataJPA核心技术专题内再详细的讲解使用EntityManager是如何完成自定义SQL、调用存储过程、视图等等操作的。下面我们打开UserJPA接口,添加自定义查询年龄大于20的数据,如下图18所示:

     
    图18

    @Query是用来配置自定义SQL的注解,后面参数nativeQuery = true才是表明了使用原生的sql,如果不配置,默认是false,则使用HQL查询方式。我们在UserController内添加方法/age,测试我们的自定义SQL是否有效,代码如下图19所示:

     
    图19

    重启下项目,访问127.0.0.1:8080/age,效果如下图20所示:

     
    图20

    @Query配合@Modifying

    从名字上可以看到我们的@Query注解好像只是用来查询的,但是如果配合@Modifying注解一共使用,则可以完成数据的删除、添加、更新操作。下面我们来测试下自定义SQL完成删除数据的操作,我根据名字、密码字段共同删除一个数据,接口代码如下图21所示:

     
    图21

    我们再来编写UserController添加对应的方法调用deleteQuery接口方法,如下图22所示:

     
    图22

    重启下项目,访问地址:127.0.0.1:8080/deleteWhere,界面输出内容如下图23所示:

     
    图23

    界面竟然出现了异常,这是怎么回事呢?可以看到抛出的异常TranscationRequiredException,意思就是你当前的操作给你抛出了需要事务异常,SpringDataJPA自定义SQL时需要在对应的接口或者调用接口的地方添加事务注解@Transactional,来开启事务自动化管理。下面我们在UserJPA内添加@Transactional注解,重启项目再来访问刚才的地址,效果如下图24所示:

     
    图24

    界面已经给我提示了删除成功,我们查看下控制台看打印的SQL是否是我们自定义的,如下图25所示:

     
    图25

    我们自定义的SQL被成功的打印了,自定义SQL完成添加,更新操作时跟删除一致,都需要添加@Query以及@Modifying注解配合使用。

    自定义BaseRepository

    项目在正常情况下不仅仅只继承一个JpaRepository接口,下一章我们整合SpringDataJPA跟QueryDSL时就需要添加多个接口继承了,那么我们业务数据接口每一个都去继承几个相同的接口?答案肯定是 NO,当然多个继承也是可以的,不过对于系统设计还有代码复用性来说并不是最好的选择!

    我们创建一个包名叫做base,在包内添加一个BaseRepository接口,并且接口继承我们的JpaRepository,代码如下图26所示:

     
    图26

    又出现了一个新的注解,@NoRepositoryBean,这个注解是用来干什么的呢?

    Spring开源程序猿在命名规则上应该是比较严格的,从名字上我们几乎就可以判断出用途,这个注解如果配置在继承了JpaRepository接口以及其他SpringDataJpa内部的接口的子接口时,子接口不被作为一个Repository创建代理实现类。

    我们创建的业务数据接口直接继承BaseRepository就行了,继承的子接口会拥有JpaRepository所有方法实现。

    分页查询

    分页对于大型系统来说肯定是必不可少的,那么我们在SpringDataJpa内是如何使用分页来完成查询的呢?

    一般情况我们会创建一个BaseEntity,在BaseEntity内添加几个字段:排序列,排序方式,当前页码,每页条数等,下面我们也来创建这么一个父类,代码如下图27所示:

     
    图27

    我们修改UserEntity继承BaseEntity,然后在数据库内添加上几条测试数据,我们每次页面的数量就不用20了,我们在创建查询条件时修改成2条。

    我们打开UserController添加cutPage方法,用于作为分页查询入口,(注意:文章的讲解都没有添加Service层所以所有的业务逻辑都在Controller内处理的,正式项目请不要这样编写。)我们在cutPage方法内添加对应的分页逻辑,如下图28所示:

     
    图28

    接下来我们重启下项目,访问地址:127.0.0.1:8080/cutpage?page=1,查看界面输出效果如下图29所示:

     
    图29

    我们再来看下控制台的输出,如下图30所示:

     
    图30

    可以看到控制台给我们打印了两条SQL,第一条是分页查询的SQL,第二条是查询表内总数量的SQL。SpringDataJPA内部对数量做出了封装,你可以通过Page对象也就是PagingAndSortingRepository接口内的findAll(PageRequest request)方法的返回值类型中获取到总条数、总页数。

    数据排序

    我们上面在BaseEntity内添加了排序的字段以及排序方式,我们重新编辑下cutPage方法,修改pageRequest创建方式,添加Sort对象到PageRequest对象内,就可以实现排序数据。如下图31所示:

     
    图31

    上图31可以看到我们修改了排序字段我们使用了默认的id,(注意:这里的排序字段不是数据库内的字段名而是实体内的属性名)以及排序方式改成了倒序,SpringDataJPA对排序方式添加了一个枚举类型,创建Sort对象时也需要枚举对象,因为我们BaseEntity配置的是字符串所以上面多了一步判断排序方式返回枚举对象。

    重启下项目,再来访问分页路径,界面输出效果如下图32所示:

     
    图32

    可以看到数据已经是倒序方式展示了,控制台的日志输出也对应的添加了order by语句,如下图33所示:

     
    图33

    总结

    综上所述本章的内容已经讲解完了,本章的内容比较多昨天完成没有编写完,还请见谅。本章主要讲解了SpringBoot项目中使用SpringDataJPA的基本操作,包括了:CURD、分页、排序、自定义SQL、定义BaseRepository、事务处理等。本章内容并不是SpringDataJPA全面内容,后续我会在SpringDataJPA核心技术专题详细讲解。

    本章内容已经更新到码云:

    SpringBoot配套源码地址:https://gitee.com/hengboy/spring-boot-chapter

    SpringCloud配套源码地址:https://gitee.com/hengboy/spring-cloud-chapter

    SpringBoot相关系列文章请访问:目录:SpringBoot学习目录

    QueryDSL相关系列文章请访问:QueryDSL通用查询框架学习目录

    SpringDataJPA相关系列文章请访问:目录:SpringDataJPA学习目录

    SpringBoot相关文章请访问:目录:SpringBoot学习目录,感谢阅读!




  • 相关阅读:
    vivado工程移植
    Search Everything 多项查找
    RTL_代码覆盖率
    在ARTIX-7上实现摄像头视频通路
    转:自动生成testbench
    转:winedt中显示中文
    Zynq和microblaze的区别
    转:找不到include xgpio.h;Unresolved include xgpio.h
    DHTMLX 常用技术
    Ubuntu中安装 mercurial – TortoiseHG
  • 原文地址:https://www.cnblogs.com/guokezhiren/p/9264401.html
Copyright © 2011-2022 走看看