Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)

​ 在开发中,通常会涉及到对数据库的数据进行操作,Spring Boot在简化项目开发以及实现自动化配置的基础上,对关系型数据库和非关系型数据库的访问操作都提供了非常好的整合支持。

​ 本章,将对Spring Boot的数据访问进行介绍,并对常用的数据操作框架进行整合讲解。

3.1 Spring Boot数据访问概述

Spring Boot默认采用整合SpringData的方式统一处理数据访问层,通过添加大量自动配置,引入各种数据访问模板xxxTemplate以及统一的Repository接口,从而达到简化数据访问层的操作。

  • Spring Boot提供的常见数据库依赖启动器

    名称 对应数据库
    spring-boot-starter-data-jpa •Spring Data JPA •Hibernate
    spring-boot-starter-data-mongodb •MongoDB •Spring Data MongoDB
    spring-boot-starter-data-neo4j •Neo4j图数据库 •Spring Data Neo4j
    spring-boot-starter-data-redis •Redis
  • 官方没有提供的数据库,如Mybatis,其开发团队自己适配了Spring Boot,提供了mybatis-spring-boot-starter依束启动器实现数据访问操作。

3.2 Sping Boot整合MyBatis

MyBatis是一款优秀的持久层框架,支持定制化SQL、存储过程以及高级映射,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集:

3.2.1 基础环境搭建

  • 步骤1:MYSQL安装准备,这里使用phpstudy直接准备,默认端口3306,用户名和密码都是root,正常运行效果如图。
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第1张图片

  • 步骤2:数据准备。可以使用http://localhost/phpymyamdin(如果网页端口非80端口,比如88端口,需要改为实际端口,http://localhost:88/phpymyamdin)访问数据库并创建数据,也可以使用SQLyog访问,这里介绍SQLyog访问方法。

    • 1)安装SQLyog
    • 2)连接到我的SQL主机
      Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第2张图片
      • 3)创建数据库:springbootdata,命令:CREATE DATABASE springbootdata;
        Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第3张图片
  • 4)创建数据表 t_article,操作方法同上。

    CREATE TABLE `t_article` (
      `id` INT(20) NOT NULL AUTO_INCREMENT COMMENT '文章id',
      `title` VARCHAR(200) DEFAULT NULL COMMENT '文章标题',
      `content` LONGTEXT COMMENT '文章内容',
      PRIMARY KEY (`id`)
    ) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
    
    1. t_article表中插入数据,操作方法同上。
    INSERT INTO `t_article` VALUES ('1', 'Spring Boot基础入门', '从入门到精通讲解...');
    INSERT INTO `t_article` VALUES ('2', 'Spring Cloud基础入门', '从入门到精通讲解...');
    
  • 6)创建数据表t_comment,操作方法同上。代码:

    CREATE TABLE `t_comment` (
      `id` INT(20) NOT NULL AUTO_INCREMENT COMMENT '评论id',
      `content` LONGTEXT COMMENT '评论内容',
      `author` VARCHAR(200) DEFAULT NULL COMMENT '评论作者',
      `a_id` INT(20) DEFAULT NULL COMMENT '关联的文章id',
      PRIMARY KEY (`id`)
    ) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    
  • 6)t_comment表中插入数据:

    INSERT INTO `t_comment` VALUES ('1', '很全、很详细', '狂奔的蜗牛', '1');
    INSERT INTO `t_comment` VALUES ('2', '赞一个', 'tom', '1');
    INSERT INTO `t_comment` VALUES ('3', '很详细', 'kitty', '1');
    INSERT INTO `t_comment` VALUES ('4', '很好,非常详细', '张三', '1');
    INSERT INTO `t_comment` VALUES ('5', '很不错', '张杨', '2');
    

    完成后效果如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第4张图片

  • 步骤3:创建项目,引入MySQL和MyBatis的依赖启动器

    1)使用Spring Initializr方式创建一个名为chapter03的Spring Boot项目(要求能联网)
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第5张图片
    2)设置项目的Group,Artifact和Package,按next
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第6张图片
    3)在Dependencies依赖中选择SQL模块中的MySQL和MyBatis依赖,点击next
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第7张图片
    4)设置存储路径,按Finish,完成项目创建。

  • 步骤3:编写配置文件

    1)创建在com.itheima下创建包domain,再创建实体类Comment

  1. 为实体类Comment创建4个变量

    package com.itheima.domain;
    
    public class Comment {
        private Integer id;
        private String content;
        private String author;
        private Integer aId;
    }
    

    在Comment方法空白处,按ALT+Insert,生成Getter和Setter方法.

  • 同样方法在domain,创建实体类Article,为实体类Article创建4个变量:

    public class Article {
        private Integer id;
        private String title;
        private String content;
        private List<Comment> commentList;}//一篇文章存在多个评论,所在这里使用集合
    
    

    在Article方法空白处,按ALT+Insert,生成各变量的Getter和Setter方法,效果如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第8张图片

    • 在application.properties配置文件中进行数据库连接配置。
    spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=root
    
    

    说明:第一行为驱动,第二行为数据库连接地址,3306一般是数据库默认端口,springbootdata为数据库名。用户名和 密码请按实际填写。

  • 步骤4:Spring Boot 1.x默认使用的是tomcat.jdbc数据库,Spring Boot 2.X版本默认使用的是hikari数据源。其他数据源需要另行配置。这里演示阿里巴巴的Druid数据源配置

    • 1)pom.xml文件中添加Druid数据源的依赖启动器,示例代码如下:

      
      
          com.alibaba
          druid-spring-boot-starter
          1.1.10
      
      
      
    • 2)上述启动器默认初始化了一些运行参考,如果需要修改,则必须在全局配置文件中修改,示例如图。

      #添加并配置第三方数据源Druid
      #数据源类型
      spring.datasource.type = com.alibaba.druid.pool.DruidDataSource
      #初始化连接数
      spring.datasource.initialSize=20
      #最小空闲数
      spring.datasource.minIdle=10
      #最大连接数
      spring.datasource.maxActive=100
      
      

Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第9张图片

    • 说明:因为在Spring Boot提供的数据源自动配置类中没有initialSize、minIdle和maxActive没有与这些参数对应的默认属性,所以这些设置的属性值 无法识别和生效。底纹为黄色显示 。为此,还需要编写一个自定义配置类。将配置文件中的属性注入到Druid数据源属性中。

    • 3)在com.itheima下创建config包,并在该包下创建一个自定义配置类对Druid数据源属性值 进行注入。内容如下:

      package com.itheima.config;
      
      import com.alibaba.druid.pool.DruidDataSource;
      import org.springframework.boot.context.properties.ConfigurationProperties;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      
      import javax.sql.DataSource;
      //通过@Configuration 标识了一个自定义配置类Datasourceconfig
      @Configuration
      public class Datasourceconfig {
          @Bean //通过@Bean注解注入一个DataSource实例对象
          //@ConfigurationProperties(prefix = "spring.datasource")作用:将全局配置文件中以spring.datasource开头的属性值
          // 注入到getDruid()方法并返回的DataSource类对象属性中。这样就可以完成第三方数据源参数值的注入。
          @ConfigurationProperties(prefix = "spring.datasource")
          public DataSource getDruid(){
              return new DruidDataSource();
          }
      }
      

    3.2.2 使用注解的方式整合MyBatis

    步骤如下:

  • 在com.itheima下创建包mapper,并在包下创建Mapper***接口文件***CommentMapper.java,内容如下:

    package com.itheima.mapper;
    
    import com.itheima.domain.Comment;
    import org.apache.ibatis.annotations.*;
    
    @Mapper  //表示该类是一个mybatis接口文件,是需要被 springboot进行扫描的。
    public interface CommentMapper {
        //查询方法
        @Select("select * from t_Comment where id=#{id}")
        public Comment findById(Integer id);//接口
    
        //添加方法
        @Insert("insert into t_comment values(#{id},#{content},#{author},#{aId})")
        public  void insertComment(Comment comment);
    
        //修改
        @Update("update t_commnet set content=#{content} where id=#{id}")
        public  void updateCommnet(Comment comment);
    
        //删除
        @Delete("delete from t_comment where id=#{id}")
        public  void delectComment(Integer id);
    }
    
  • 编写单元测试进行接口方法测试,这里我们使用Chapter03ApplicationTests,在该测试类中引入CommentMapper接口,并对该接口方法进行测试。内容如下:

    package com.itheima;
    
    import com.itheima.domain.Comment;
    import com.itheima.mapper.CommentMapper;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class Chapter03ApplicationTests {
    
        @Autowired //将CommentMapper接口自动装配为Sping容器的Bean
        private CommentMapper commentMapper;
    
        @Test
        public void contextLoads() {
            Comment comment = commentMapper.findById(1);//这里测试第1条记录
            System.out.println(comment);
        }
    }
    
    
  • 整合测试,执行测试方法contextLoads(),输出结果如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第10张图片

  • 因缺输入方法,显示内容为地址值 ,分别为添加Article和Comment的toString()方法(类定义的空白处按Alt+Insert,全选所有变量添加。)
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第11张图片
    运行测试方法contextLoads()效果如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第12张图片

可以看出,执行成功,但aId的属性值为null,没有映射成功。是因为数据表的名欣赏为a_id,实体类Comment使用了驼峰命名方式写成了aid.

解决方法,在全局配置文件application.properties开启驼峰命名匹配映射配置。

#开启驼峰命名匹配映射。
mybatis.configuration.map-underscore-to-camel-case=true

运行测试方法contextLoads()效果如图:
Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第13张图片

  • 3.2.3 使用配置文件的方式整合MyBtatis

    Spring Boot与MyBatis整合使用时,不仅支持注解方式,还支持XML配置文件的方式,对于数据操作比较复杂的情况,建议使用XML配置文件。。演示示例如下:

  • 步骤1:在com.itheima.mapper包中,创建一个操作数据表t_article的Mapper接口文件ArticleMapper.java,代码如下:

    package com.itheima.mapper;
    
    import com.itheima.domain.Article;
    import org.apache.ibatis.annotations.Mapper;
    
    @Mapper
    public interface ArticleMapper {
        public Article selectArticle(Integer id);
        public int updateArticle(Article article);
    }
    
    

    说明:@Mapper注解表示该类是一个MyBatis接口文件,声明了查询和更新文章操作的两个方法。

  • 步骤2:创建XML映射文件,编写对应的SQL语句。在项目的resources目录下,创建一个统一管理映射文件的包mapper,并在该包编写与ArticleMapper接口对应的映射文件ArticleMapper.xml,代码如下:

    
    
    
     
        
        
        
        
            
            
            
            
                
                
                
            
        
    
        
            UPDATE t_article
            
                
                    title=#{title},
                
                
                    content=#{content}
                
            
            WHERE id=#{id}
        
    
    
    
    
  • 步骤3:在application.properties中添加MyBatis映射文件路径的配置,示例代码如下:

    #配置mybatis的xml配置文件路径
    mybatis.mapper-locations=classpath:mapper/ArticleMapper.xml
    #配置xml映射文件中指定的实体类别名路径
    mybatis.type-aliases-package=com.itheima.domain
    
    
  • 步骤4:编写单元测试方法进行接口方法测试。这里仍使用Chapter03ApplicationTests文件。示例代码如下:

    @Autowired
    private ArticleMapper articleMapper;
    
    @Test //标注下面的方法是单元测试方法。这里仅演示Mapper接口的数据查询
    public void contextLoads2() {
        Article article = articleMapper.selectArticle(1);//这里测试第1条记录
        System.out.println(article);
    }
    
    
  • 步骤5:整合测试。执行上述的方法:contextLoads2(),效果如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第14张图片

3.3 Spring Boot整合JPA(Java Persistence API,Java持久化API)

​ JPA是Sun公司官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关系映射的工具管理Java中的关系型数据。其主要目的是简化现有的持久化开发工作和整合ORM(Object Relational Mapping,对象/关系映射)技术。Spring Data在JPA规范的基础上,充分利用其优点,提出了Spring Data JPA模块对具有ORM关系数据进行持久化操作。

3.3.1 Spring Data JPA 介绍

​ Spring Data JPA是Spring基于ORM框架、JPA规范的基础上封装的一套JPA应用框架,它提供了增删改查等常用功能,使开发者可以用较少的代码实现数据操作,同时还易于扩展。

Spring Data JPA基本使用示例:
  • 步骤1:编写ORM实体类:实体类与数据表进行映射,并且配置好映射关系。

    • 我们在chapter03项目的domain上创建实体类Discuss.java,代码如下:

      package com.itheima.domain;
      
      import javax.persistence.*;
      
      @Entity(name="t_comment")  //该注解表示实体类是与表有映射关系的实体类
      public class Discuss {
      
          @Id  //该注解表示配置该属性对应的字段为主键
          @GeneratedValue(strategy = GenerationType.IDENTITY)  //表示当前主键生成策略为自增长,可省略。支持的策略有:TABLE(使用一个特定的数据库表格来保存主键)、SEQUENCE(不支持主键自增长的数据库主键生成策略)、IDENTITY(主键自增)和AUTO(JPA自主选择前面3种合适的策略,是默认选项)
          private Integer id;
          @Column(name = "content")//映射数据表中的content字段,标注在属性上,当类属性与表字段名不同时,能够配合name属性表示类属性对应的表字段名。
          private String content;
          @Column(name = "author") //映射数据表中的author字段
          private String author;
          @Column(name = "aId")   //映射数据表中的aId字段
          private Integer aId;
      
          @Override
          public String toString() {
              return "Discuss{" +
                      "id=" + id +
                      ", content='" + content + '\'' +
                      ", author='" + author + '\'' +
                      ", aId=" + aId +
                      '}';
          }
      
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public String getContent() {
              return content;
          }
      
          public void setContent(String content) {
              this.content = content;
          }
      
          public String getAuthor() {
              return author;
          }
      
          public void setAuthor(String author) {
              this.author = author;
          }
      
          public Integer getaId() {
              return aId;
          }
      
          public void setaId(Integer aId) {
              this.aId = aId;
          }
      }
      
  • 步骤2:1.编写Repository接口:针对不同的表数据操作编写各自对应的Repositor接口,并根据需要编写对应的数据操作方法。

    • 在com.itheima下新建包Repository,创建接口文件:DiscussRepository.java,代码如下:

      package com.itheima.repository;
      
      import com.itheima.domain.Discuss;
      import org.springframework.data.domain.Pageable;
      import org.springframework.data.jpa.repository.JpaRepository;
      import org.springframework.data.jpa.repository.Modifying;
      import org.springframework.data.jpa.repository.Query;
      import org.springframework.transaction.annotation.Transactional;
      
      import java.util.List;
      
      //参数Discuss,与前面创建的实体类Discuss一致,参数Integer与主键(id)数据类型一致,通过继承JpaRepository可以获得简单的增删查改的基本操作
      public interface DiscussRepository extends JpaRepository<Discuss,Integer> {
          // 1、查询author非空的Discuss评论集合,findBy开始,接查询字段名称Author,再接查询方法NotNull,该方法是一个基本的查询方法,属于JPA支持的方法名关键字查询方法。Spring Data JPA支持的方法名关键字及对应的SQL片段说明,参考表3-2。
          public List<Discuss> findByAuthorNotNull();
      
          // 2、根据文章id分页查询Discuss评论集合
          @Query("SELECT c FROM t_comment c WHERE  c.aId = ?1")//借助该注解引入SQL语句
          public List<Discuss> getDiscussPaged(Integer aid,Pageable pageable);//自定义查询,方法名称可以不用固定的命名方法
      
          // 3、使用元素SQL语句,根据文章id分页查询Discuss评论集合
          @Query(value = "SELECT * FROM t_comment  WHERE  a_Id = ?1",nativeQuery = true)//nativeQuery = true:表明当前写的是原生SQL语句
          public List<Discuss> getDiscussPaged2(Integer aid, Pageable pageable);
      
          //4、 根据评论id修改评论作者author
          @Transactional  //作变更操作,如删改操作,需要增加此注解进行事务管理
          @Modifying  //进行数据更新和删除操作的变更操作,必须加此注解
          @Query("UPDATE t_comment c SET c.author = ?1 WHERE  c.id = ?2")
          public int updateDiscuss(String author,Integer id);
      
          // 5、根据评论id删除评论
          @Transactional
          @Modifying
          @Query("DELETE t_comment c WHERE  c.id = ?1")
          public int deleteDiscuss(Integer id);
      
      }
      

      说明: 使用Spring Data JPA自定义Repository接口,必须继承XXRepository接口。T代表要操作的实体类,ID表示实体类主键数据类型。JpaRepository接口的继承结构如图:
      Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第15张图片

        • 说明:
      • Repository接口:是Spring Data JPA提供的用于自定义Repository接口的顶级父接口,该接口中没有声明任何方法。

      • CurdRepository接口:是Repository的继承接口之一,包含了一些苦楚一的CRUD方法。

      • PagingAndSortingRepository接口:继承CrudRepository接口的同时,提供了分页和排序两个方法

      • QueryByExampleExecutor接口:是进行条件封装查询的顶级父接口,允许通过Example实例执行复杂条件查询

      • JpaRepository接口:同时继承了PagingAndSortingRepository接口和QueryByExampleExecutor接口,并额外提供了一些数据操作方法。自定义Repository接口时,通常会直接选择继承该接口。

  • 步骤3:创建测试文件Jpatests.java,代码如下:、

    package com.itheima;
    
    import com.itheima.domain.Discuss;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.List;
    import java.util.Optional;
    
    @SpringBootTest
    class JpaTests {
    
       @Autowired
        private com.itheima.repository.DiscussRepository discussRepository;
    
       @Test
       //测试JPA自带的增删改查方法
       public void test1(){
           //操作技巧:discussRepository.findById(1).var可获得下列代码,拿到返回值。
           Optional byId = discussRepository.findById(1);//findById为JPA提供的。这里指定查询第一条评论
           //操作技巧:sout,可快速获得输入语句
           System.out.println(byId.get());
       }
    
        @Test
        //测试自定义的查找方法
        public void test2(){
            //操作技巧:discussRepository.findByAuthorNotNull().var可获得下列代码,拿到返回值。
            List byAuthorNotNull = discussRepository.findByAuthorNotNull();//findByAuthorNotNull()为根据JPA规范的命名设计的方法。
            //操作技巧:返回值为多个,进行遍历的方法:byAuthorNotNull.for
            for (Discuss discuss : byAuthorNotNull) {
                System.out.println(discuss);
                
            }
        }
        @Test
        //测试删除方法,删除后查看数据表看结果
        public void test3(){
            int i = discussRepository.deleteDiscuss(4);//deleteDiscuss为自定义的删除方法,这里尝试删除查询第4条评论
            System.out.println(i);//查看影响行数
        }
    }
    
    

    这里运行test2方法,显示结果如下:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第16张图片

    3.3.2 使用Spring Boot整合JPA

重做上述案例(相同类和方法,两次建立容易出现错误),只是更细分一点,具体如下:

  • 步骤1:在pom文件中添加Spring Data JPA依赖启动器

    
    
        org.springframework.boot
        spring-boot-starter-data-jpa
    
    
    

    可以在Maven窗口中看到依赖启动器已添加。
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第17张图片

    • 步骤2:编写ORM实体类,在domain包下新建文件Discuss.java,示例代码如下:
    package com.itheima.domain;
    
    //该实体类要与t_comment表进行映射配置
    
    import javax.persistence.*;
    
    @Entity(name="t_comment")  //步骤1:添加@Entity注解,表示该类是与表有映射关系的实体类
    public class Discuss {
        @Id //步骤3:配置ID主键注解,表示该属性映射的字段为主键字段。
        @GeneratedValue(strategy = GenerationType.IDENTITY) //配置主键的生成策略
        //步骤2:复制Comment类中的四个与表对应的属性过来
        private Integer id;
    
        @Column(name = "content")//步骤4:配置其他3个属性与数据表的字段对应
        private String content;
        @Column(name = "author")
        private String author;
        @Column(name = "aId")
        private Integer aId;
    
        //步骤6:按Alt+Insert,全选四属性,生成toString方法
    
        @Override
        public String toString() {
            return "Discuss{" +
                    "id=" + id +
                    ", content='" + content + '\'' +
                    ", author='" + author + '\'' +
                    ", aId=" + aId +
                    '}';
        }
    
    
        //步骤5:按Alt+Insert,全选四属性,生成Getter和Setter方法
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    
        public Integer getaId() {
            return aId;
        }
    
        public void setaId(Integer aId) {
            this.aId = aId;
        }
    }
    
    
  • 步骤3:在com.itheima下创建包repository,编写Repository接口文件DiscussRepository.java,具体代码如下:

    package com.itheima.repository;
    
    //编写过程如果有需要调用的部分,按Alt+Enter会自动添加import部分内容
    import com.itheima.domain.Discuss2;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.Modifying;
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.List;
    
    //步骤1:让接口继承JpaRepository,并添加两参数(Discuss2,Integer),说明当前接口操作的实体类及主键的类型
    //继承了JpaRepository的接口,具有了简单的增删改查的方法。
    public interface DiscussRepository2 extends JpaRepository<Discuss2,Integer>{
        //步骤2:完成需求1,查询author非空的Discuss评论集合,findBy开始,接查询字段名称Author,再接查询方法NotNull
        public List<Discuss2> findByAuthorNotNull();
    
        // 步骤3:完成需求2,根据文章id分页查询Discuss评论集合
        @Query("SELECT c FROM t_comment c WHERE  c.aId = ?1")//借助该注解引入SQL语句,?1:占位符,表示取出参数中的第1个值赋值给c.aId
        public List<Discuss2> getDiscussPaged(Integer aid, Pageable pageable);//自定义查询,方法名称可以不用固定的命名方法
    
        // 步骤4:使用元素SQL语句,根据文章id分页查询Discuss评论集合
        @Query(value = "SELECT * FROM t_comment  WHERE  a_Id = ?1",nativeQuery = true)//nativeQuery = true:表明当前写的是原生SQL语句,含*号
        public List<Discuss2> getDiscussPaged2(Integer aid, Pageable pageable);
    
        //步骤5:根据评论id修改评论作者author
        @Transactional  //作增删改操作,需要增加此注解
        @Modifying  //该注解表示当前操作会对数据进行更新和删除的变更操作
        @Query("UPDATE t_comment c SET c.author = ?1 WHERE  c.id = ?2")
        public int updateDiscuss(String author,Integer id);
    
        // 步骤6:根据评论id删除评论
        @Transactional
        @Modifying
        @Query("DELETE t_comment c WHERE  c.id = ?1")
        public int deleteDiscuss(Integer id);
    
    }
    
  • 步骤4:编写单元测试进行接口方法测试及整合测试,复印chapter03ApplicationTests.java,命名为JpaTest.java,示例代码如下:

    package com.itheima;
    
    import com.itheima.domain.Discuss;
    import com.itheima.repository.DiscussRepository;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.List;
    import java.util.Optional;
    
    @SpringBootTest
    class JpaTests {
    
       @Autowired
        private DiscussRepository discussRepository;
    
       @Test
       //测试JPA自带的增删改查方法
       public void test1(){
           //操作技巧:discussRepository.findById(1).var可获得下列代码,拿到返回值。
           Optional<Discuss> byId = discussRepository.findById(1);//findById为JPA提供的。这里指定查询第一条评论
           //操作技巧:sout,可快速获得输入语句
           System.out.println(byId.get());
       }
    
        @Test
        //测试自定义的查找方法
        public void test2(){
            //操作技巧:discussRepository.findByAuthorNotNull().var可获得下列代码,拿到返回值。
            List<Discuss> byAuthorNotNull = discussRepository.findByAuthorNotNull();//findByAuthorNotNull()为根据JPA规范的命名设计的方法。
            //操作技巧:返回值为多个,进行遍历的方法:byAuthorNotNull.for
            for (Discuss discuss : byAuthorNotNull) {
                System.out.println(discuss);
                
            }
        }
        @Test
        //测试删除方法,删除后查看数据表看结果
        public void test3(){
            int i = discussRepository.deleteDiscuss(4);//deleteDiscuss为自定义的删除方法,这里尝试删除查询第4条评论
            System.out.println(i);//查看影响行数
        }
    }
    
  • 测试test1效果如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第18张图片

3.4 Spring Boot整合Redis

除了对关系型数据库的整合支持外,Spring Boot对非关系型数据库也提你菊花了非常好的支持。本节u将讲解Sping Boot与非关系型数据库Redis的整合使用。

3.4.1 Redis介绍

Redis学习资料请参考:https://www.runoob.com/redis/redis-intro.html

Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。

Redis 与其他 key - value 缓存产品有以下三个特点:

  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份

相较于其他的key-value键值存储系统,Redis有以下优点:

  • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
1.Redis的下载安装
  • 在GitHub上下载Windows平台下的Redis安装包解压到自定义目录即可,这里使用版本为3.2.100.参考网址:https://github.com/microsoftArchive/redis/releases
2.Redis服务开启与连接配置
  • 步骤1:开启Redis服务。进入到解压的文件包中,如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第19张图片

  • 说明:redis-server.exe用于开启Redis服务,redies-cli.exe用于开启客户端工具。

  • 步骤2:双击redis-server.exe指令开启Redis服务。效果如图所示:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第20张图片

  • 步骤3:因为redies-cli.exe是终端操作界面,不方便可视化操作帮查看。这里推荐使用一个Redis客户端可视化管理工具Redis Desktop Manager来连接Redis服务进行管理。相关软件可在redisdestop官网进行下载安装。安装后执行效果如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第21张图片

  • 说明:name可自定义,Host为本机时,可写为127.0.0.1,端口默认为6379

  • 单击OK,即可进入可视化界面。
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第22张图片

  • 3.4.2 使用Spring Boot整合Redis

    在项目chapter03基础上继承完成Spring Boot整合Redis,具体步骤如下:

  • 步骤1:在pom文件中添加Spring Data Redis依赖启动器

    
    
        org.springframework.boot
        spring-boot-starter-data-redis
    
    
    
  • 步骤2:编写实体类Person,需要注意的是Person类包含地址类(Address)和家庭成员类(Family),所以在定义Person类的Address和Family属性时,可以按下图方法快捷生成Address类和Family类,如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第23张图片
    在打开的窗口中存放的包的位置,这里就在domain包下。如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第24张图片
    Person实类体代码如下:

package com.itheima.domain;

import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;

import java.util.List;

//步骤1:添加@RedisHash注解:会在Redis中开启一块存储空间,名称叫"persons",对实体类Person的数据操作都会存在这空间。
@RedisHash("persons")
public class Person {
    //步骤2:添加5个属性
    @Id //注意不要导错包,该注解用于标识实体类主键
    private String id;
    @Indexed  //用于标识该属性会在redis数据库中生成二级索引
    private String firstname; //存储:姓
    @Indexed
    private String lastname;  //存储:名
    //步骤3:添加实体类Address,快捷方法:在Address后按Alt+Enter键,选"Create class Address",在domain包中生在Address类
    //同样方法生成Family类
    private Address address;  //居住地址类
    private List<Family> familyList; //家庭成员类

    //步骤5:按Alt+Insert键生成各属性的Getter和Setter方法
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public List<Family> getFamilyList() {
        return familyList;
    }

    public void setFamilyList(List<Family> familyList) {
        this.familyList = familyList;
    }

    //步骤6:为后续输出方便,按Alt+Insert键生成toString方法
    @Override
    public String toString() {
        return "Person{" +
                "id='" + id + '\'' +
                ", firstname='" + firstname + '\'' +
                ", lastname='" + lastname + '\'' +
                ", address=" + address +
                ", familyList=" + familyList +
                '}';
    }
}
  • 步骤3:编写实体类Address代码,生成Getter和Setter方法,代码如下:

    package com.itheima.domain;
    
    import org.springframework.data.redis.core.index.Indexed;
    
    public class Address {
        @Indexed  //用于标识该属性会在redis数据库中生成二级索引
        private String city;
        @Indexed
        private String country;
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        public String getCountry() {
            return country;
        }
    
        public void setCountry(String country) {
            this.country = country;
        }
    }
    
  • 步骤4:编写实体类Family代码,生成Getter和Setter方法,代码如下:

    package com.itheima.domain;
    
    import org.springframework.data.redis.core.index.Indexed;
    
    public class Family {
        @Indexed  //用于标识该属性会在redis数据库中生成二级索引
        private String type;
        @Indexed
        private String username;
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    }
    
    
  • 步骤5:在包Repository下,编写Repository接口文件PersonRepository.java,具体代码如下:

    package com.itheima.repository;
    
    import com.itheima.domain.Person;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.repository.CrudRepository;
    
    import java.util.List;
    
    //步骤1:继承CrudRepository接口,注意一定要有两个参数,:分别表示类名和类名的主键数据类型
    public interface PersonRepository extends CrudRepository<Person,String> {
        //步骤2:导入五个方法,注意import class 导入相关的包
        List<Person> findByLastname(String lastname);//根据姓氏查询某人
        Page<Person> findPersonByLastname(String lastname, Pageable page);//根据姓氏查询某人,加了分页
        List<Person> findByFirstnameAndLastname(String firstname, String lastname);//根据姓名查询某人
        List<Person> findByAddress_City(String city);//根据这座城市居住的人
        List<Person> findByFamilyList_Username(String username);//根据某一个人的名字查询家庭成员。
    
    }
    
  • 步骤6:在全局配置文件application.properties中添加Redis数据库连接配置,代码如下:

    #配置redis连接,请按实际配置,这里按本地的未设密码,默认端口的设置进行配置。
    #redis服务器地址
    spring.redis.host=127.0.0.1
    #redis连接端口
    spring.redis.port=6379
    #redis服务连接密码
    spring.redis.password=
    
    
  • 步骤7:编写单元测试文件进行接口方法测试。这里将Chapter03ApplicationTests.java在当前位置复制一份,并重命名为RedisTests.java。代码如下:

    package com.itheima;
    
    import com.itheima.domain.Address;
    import com.itheima.domain.Family;
    import com.itheima.domain.Person;
    import com.itheima.repository.PersonRepository;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;
    //拟测试接口的方法是否能执行以及Spring Boot和redis是否整合成功
    @SpringBootTest
    class RedisTests {
        //步骤1:注入PersonRepository
        @Autowired
        private PersonRepository personRepository;
    
        //步骤2:编写测试一个添加方法
        @Test
        public void savePerson(){
            Person person = new Person();//创建对象
            person.setFirstname("有才");//设置person对象的名字为有才
            person.setLastname("张");   //设置person对象的姓氏为张
    
            Address address = new Address(); //创建地址对象
            address.setCity("北京");  //设置地址为北京
            person.setAddress(address); //设置person对象的地方
            Family family = new Family();//创建家庭成员对象1
            family.setType("父亲");
            family.setUsername("张三");
            Family family2 = new Family();//创建家庭成员对象2
            family2.setType("母亲");
            family2.setUsername("李香");
    
            ArrayList<Family> families = new ArrayList<>();
            families.add(family);
            families.add(family2);
    
            person.setFamilyList(families);//将多个成员对象存入person的相关属性值中
    
            personRepository.save(person);//调用接口默认方法,存入person对象
    
        }
    }
    
  • 步骤8:运行savePerson()方法,效果如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第25张图片
    查看是否存放redis,结果如图:
    Spring Boot 实践之六 Spring Boot数据访问(Sping Boot整合MyBatis/Sping Boot整合JPA/Sping Boot整合Redis)_第26张图片
    至此,Sping Boot整合Redis成功。

你可能感兴趣的:(Spring,Boot)