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学习目录,感谢阅读!




  • 相关阅读:
    序列JSON数据和四种AJAX操作方式
    jquery.validate和jquery.form.js实现表单提交
    JQuery Validate使用总结1:
    HOWTO: Include Base64 Encoded Binary Image Data (data URI scheme) in Inline Cascading Style Sheets (CSS)(转)
    SharePoint 2007 使用4.0 .Net
    动态IP解决方案
    取MS CRM表单的URL
    从Iframe或新开的窗口访问MS CRM 2011(转)
    Toggle or Hidden MS CRM Tab
    Windows 2008下修改域用户密码
  • 原文地址:https://www.cnblogs.com/guokezhiren/p/9264401.html
Copyright © 2011-2022 走看看