Spring Boot | Spring Boot“整合Redis“

目录:

    • 1. Redis 介绍
    • 2. Redis 下载安装
    • 3. Redis “服务开启”和“连接配置”
    • 4. Spring Boot整合Redis的“前期准备” :
      • ① 编写实体类
      • ② 编写Repository 接口
      • ③ 在“全局配置文件”中添加 “Redis数据库” 的 “相关配置信息”
      • 5. Spring Boot整合“Redis” (案例展示)

        作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!

        该文章参考学习教材为:

        《Spring Boot企业级开发教程》 黑马程序员 / 编著

        文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章

        文章用于本人学习使用 , 同时希望能帮助大家。

        欢迎大家点赞👍 收藏⭐ 关注💖哦!!!

        (侵权可联系我,进行删除,如果雷同,纯属巧合)


        • Spring Boot 除了关系型数据库整合支持 外,Spring Boot对 非关系型数据库 也提供了非常好的支持。如 : Spring Boot对 非关系型数据库Redis 的 整合使用。

        1. Redis 介绍

        • Redis 是一个 开源(BSD 许可)的、内存 中的 数据结构存储系统 ,它可以用作 数据库缓存消息中间件,并提供多种语言的API。

        • Redis 支持 多种类型数据结构,例如 字符串(strings)、散列( hashes )、列表( lists )、集合( sets)等。同时,Redis内部内置了复本(replication)、LUA 脚本( Lua scripting )、LRU 驱动事件( LRU eviction )、事务(Transaction)和 不同级别的磁盘持久化( persistence ),并通过Redis Sentinel 和 自动分区提供高可用性( high availability )。相较于其他的 key-value 键值存储系统而言,

          Redis主要有以下优点

          存取速度快 : Redis 速度非常快,每秒可执行大约 110000次 的 设值操作,或者执行 81000 次的 读取操作

          支持丰富的数据类型 : Redis 支持开发人员常用的大多数数据类型,例如列表、集合、排序集和散列等。

          操作具有原子性 : 所有 Redis 操作 都是 原子操作,这确保如果两个客户端并发访问,Redis服务器能接收更新后的值。

          提供多种功能 : Redis 提供了多种功能特性,可用作非关系型数据库、缓存中间件、消息中间件等。

        2. Redis 下载安装

        • Redis下载安装

          Redis入门 (Redis下载安装)-跳转博客

        3. Redis “服务开启”和“连接配置”

        • 完成 Redis 的下载安装后,启动Redis 服务,并使用 可视化客户端工具 连接对应的Redis

          服务进行效果测试,具体操作步骤如下 :

          (1) 开启Redis服务

          (2) Redis可视化客户端工具正常安装连接

          Redis入门 (Redis “服务开启”和“连接配置”)-跳转博客

        4. Spring Boot整合Redis的“前期准备” :

        ① 编写实体类

        • 编写实体类中最重要的是懂得使用SpringBoot整合Redis中的常用注解

          注解描述
          @RedisHash( " 存储空间的名称" )注解用于指定操作 实体类对象Redis 数据库 中的 存储空间
          :
          @RedisHash(“persons”) 表示此处的的Redis数据都存储在 Redis 数据库中 名为 persons存储空间 下。
          @ld注解用于 标识实体类 “主键”。在Redis数据库中会 默认生成“字符串形式”HashKey 表示 唯一 的实体对象id,当然也可以在数据存储时 手动指定id
          @Indexed注解用于 标识 “对应属性” 在Redis数据库中 生成二级索引使用该注解后会在Redis数据库中生成属性对应二级索引索引名称就是属性名,可以方便地进行数据条件查询。
        • 例子如 :

          person.java( 实体类 ) :

          package com.myh.chapter_08.domain;
          import org.springframework.data.annotation.Id;
          import org.springframework.data.redis.core.RedisHash;
          import org.springframework.data.redis.core.index.Indexed;
          @RedisHash("RedisPersonInfo") //将要存储的数据都存储在Redis数据库中的RedisPersonInfo的这个命名空间下
          public class Person { @Id //标识“实体类”的“主键”
              private String id;
              //在redis数据库中生成“属性”对应的“二级索引”
              @Indexed //表述该属性,在redis数据库中生成"二级索引" (“索引名”就是“属性名”)
              private String firstname;
              @Indexed //在数据库中生成“属性”对应的“二级索引”
              private String lastname;
              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;
              }
              @Override
              public String toString() { return "Person{" +
                          "id='" + id + '\'' +
                          ", firstname='" + firstname + '\'' +
                          ", lastname='" + lastname + '\'' +
                          '}';
              }
              public Person(String id, String firstname, String lastname) { this.id = id;
                  this.firstname = firstname;
                  this.lastname = lastname;
              }
              public Person() { //无参构造方法
              }
          }
          

          Address.java :

          package com.myh.chapter_08.domain;
          import org.springframework.data.annotation.Id;
          import org.springframework.data.redis.core.RedisHash;
          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;
              }
              @Override
              public String toString() { return "Address{" +
                          "city='" + city + '\'' +
                          ", country='" + country + '\'' +
                          '}';
              }
              public Address(String city, String country) { this.city = city;
                  this.country = country;
              }
              public Address() { }
          }
          

          Address.java :

          package com.myh.chapter_08.domain;
          import org.springframework.data.redis.core.index.Indexed;
          public class Family { @Indexed
              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;
              }
              public Family(String type) { this.type = type;
              }
              @Override
              public String toString() { return "Family{" +
                          "type='" + type + '\'' +
                          ", username='" + username + '\'' +
                          '}';
              }
              public Family(String type, String username) { this.type = type;
                  this.username = username;
              }
              public Family() { //无参构造方法
              }
          }
          

        ② 编写Repository 接口

        • Spring Boot 针对包括 Redis在内 的一些 常用数据库 提供了 自动化配置,可以通过 实现 Repository接口 简化 对数据库中的数据进行的 增删改查操作,这些操作方法同 Spring Data JPA操作数据的使用方法基本相同,可以使用方法名关键字行数据操作

          (方法名关键字查询(也称为 方法名约定查询)是一种 约定大于配置查询方式。这种方式允许开发者通过简单的方法命名来定义查询 ( 方法的命名是有一定的规律的 ) )

        • 例子如

          PersonRepository.java ( Repository接口 )

          package com.myh.chapter_08.Repository.Repository;
          import com.myh.chapter_08.domain.Person;
          import org.springframework.data.domain.Page;
          import org.springframework.data.domain.Pageable;
          import org.springframework.data.repository.CrudRepository;
          import java.util.List;
          //CrudRepository , T表示实体类对象类型; ID表示实体类中的主键的“类型”
          public interface PersonRepository extends CrudRepository { //Person类对应的"Repository接口" : 该接口中为"操作数据库"的"方法"
              /**
               * 使用"方法名关键字" 的方式进行数据操作 :
               *
               */
              //根据lastname属性值进行数据查询
              //相当于 select * from 表名 where lastname = ?1
              List findByLastname(String lastname);
              //根据lastname属性进行“分页查询”
              //findPersonByLastname 中的 Person表示“最后的返回值”为Person类型对象 (当然还要结合形成“分页效果”)
              Page findPersonByLastname(String lastname, Pageable page);
              //根据firstname 和 lastname两个参数进行数据查询
              //相当于 select * from 表名 where firstname = ?1 and lastname = ?2
              List findByFirstnameAndLastname(String firstname, String lastname);
              /*
                 根据city属性进行查询 (但这个city属性为Person对象中的Address对象类型属性中的子属性),所以用Address_City这种表示形式
                 findByAddress_City 本质上和 findByLastname 都是“同一种” "方法名关键字查询"的方式 (Address_City 表示 Address对象属性中的子属性)
               */
              List findByAddress_City(String city); //根据City属性查询数据
              /*
                 findByFamilyList_Username 本质上和 findByLastname
                 都是“同一种” "方法名关键字查询"的方式 (FamilyList_Username 表示 Family对象属性中的子属性)
               */
              List findByFamilyList_Username(String usernmae); //根据usernmae属性查询数据
          }
          

          在上面的代码中,PersonRepository接口 继承CrudRepository接口,该接口中定义了若干查询方法。需要说明的是,在 操作Redis 数据库时编写的 Reposiitory 接口 文件 需要继承CrudRepository接口,而 不是继承JpaRepository,这是因为 JpaReposiitory 是 Spring Boot 整合 JPA特有的。当然,也可以在项目pom.xml 文件中同时导入Spring Boot 整合的 JPA 依赖和 Redis依赖,这样就可以编写一个继承JpaRepository 的接口操作 Redis数据库了。

        ③ 在“全局配置文件”中添加 “Redis数据库” 的 “相关配置信息”

        #配置Redis数据库连接信息/连接参数
        #Redis服务器地址
        spring.redis.host = 127.0.0.1
        #Redis服务器连接端口(默认为6379)
        spring.redis.port=6379
        #Redis服务连接器密码(默认为空)
        spring.redis.password=root
        

        上述代码中,在Spring Boot项目的全局配置文件application.properties 中额外添加了 Redis数据库的相关配置信息,这与之前介绍的使用 Redis 客户端可视化工具连接设置的参数基本一致。除了一些基本配置外,还可以根据需要添加Redis数据库相关的其他配置。

        注意点

        在上述示例 application.properties 中主要配置了Redis数据库的 服务地址端口号,而Spring Boot内部默认 Redis服务地址为本机( localhost 或 127.0.0.1),服务端口号为6379,这与前面开启的Redis服务一致,所以这种情况下省略上述配置,仍可以正常连接访问本地开启的Redis服务。

        5. Spring Boot整合“Redis” (案例展示)

        • Spring Boot整合“Redis” ,例子如 :

          创建项目

          Address.java :

          package com.myh.chapter_08.domain;
          import org.springframework.data.annotation.Id;
          import org.springframework.data.redis.core.RedisHash;
          import org.springframework.data.redis.core.index.Indexed;
          public class Address { @Indexed //表述该属性,在redis数据库中生成"二级索引" (“索引名”就是“属性名”)
              private String city;
              @Indexed //在数据库中生成“属性”对应的“二级索引”
              private String country;
              //省略属性的get、set方法
              //省略有参和无参构造方法
              //省略toString()方法
              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;
              }
              @Override
              public String toString() { return "Address{" +
                          "city='" + city + '\'' +
                          ", country='" + country + '\'' +
                          '}';
              }
              public Address(String city, String country) { this.city = city;
                  this.country = country;
              }
              public Address() { }
          }
          

          Family.java :

          package com.myh.chapter_08.domain;
          import org.springframework.data.redis.core.index.Indexed;
          public class Family { @Indexed
              private String type;
              @Indexed
              private String username;
              //省略属性的get、set方法
              //省略有参和无参构造方法
              //省略toString()方法
              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;
              }
              public Family(String type) { this.type = type;
              }
              @Override
              public String toString() { return "Family{" +
                          "type='" + type + '\'' +
                          ", username='" + username + '\'' +
                          '}';
              }
              public Family(String type, String username) { this.type = type;
                  this.username = username;
              }
              public Family() { //无参构造方法
              }
          }
          

          Person.java :

          package com.myh.chapter_08.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;
          @RedisHash("RedisPersonInfo") //将要存储的数据都存储在Redis数据库中的RedisPersonInfo的这个命名空间下
          public class Person { @Id //标识“实体类”的“主键”
              private String id;
              //在redis数据库中生成“属性”对应的“二级索引”
              @Indexed //表述该属性,在redis数据库中生成"二级索引" (“索引名”就是“属性名”)
              private String firstname;
              @Indexed //在数据库中生成“属性”对应的“二级索引”
              private String lastname;
              private Address address;
              private List familyList;
              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 getFamilyList() { return familyList;
              }
              public void setFamilyList(List familyList) { this.familyList = familyList;
              }
              @Override
              public String toString() { return "Person{" +
                          "id='" + id + '\'' +
                          ", firstname='" + firstname + '\'' +
                          ", lastname='" + lastname + '\'' +
                          ", address=" + address +
                          ", familyList=" + familyList +
                          '}';
              }
              public Person(String id, String firstname, String lastname, Address address, List familyList) { this.id = id;
                  this.firstname = firstname;
                  this.lastname = lastname;
                  this.address = address;
                  this.familyList = familyList;
              }
              public Person() { //无参构造方法
              }
              public Person(String firstname, String lastname) { this.firstname = firstname;
                  this.lastname = lastname;
              }
          }
          

          PersonRepository.java :

          package com.myh.chapter_08.Repository.Repository;
          import com.myh.chapter_08.domain.Person;
          import org.springframework.data.domain.Page;
          import org.springframework.data.domain.Pageable;
          import org.springframework.data.repository.CrudRepository;
          import java.util.List;
          //CrudRepository , T表示实体类对象类型; ID表示实体类中的主键的“类型”
          public interface PersonRepository extends CrudRepository { //Person类对应的"Repository接口" : 该接口中为"操作数据库"的"方法"
              /**
               * 使用"方法名关键字" 的方式进行数据操作 :
               *
               */
              //根据lastname属性值进行数据查询
              //相当于 select * from 表名 where lastname = ?1
              List findByLastname(String lastname);
              //根据lastname属性进行“分页查询”
              //findPersonByLastname 中的 Person表示“最后的返回值”为Person类型对象 (当然还要结合形成“分页效果”)
              Page findPersonByLastname(String lastname, Pageable page);
              //根据firstname 和 lastname两个参数进行数据查询
              //相当于 select * from 表名 where firstname = ?1 and lastname = ?2
              List findByFirstnameAndLastname(String firstname, String lastname);
              /*
                 根据city属性进行查询 (但这个city属性为Person对象中的Address对象类型属性中的子属性),所以用Address_City这种表示形式
                 findByAddress_City 本质上和 findByLastname 都是“同一种” "方法名关键字查询"的方式 (Address_City 表示 Address对象属性中的子属性)
               */
              List findByAddress_City(String city); //根据City属性查询数据
              /*
                 findByFamilyList_Username 本质上和 findByLastname
                 都是“同一种” "方法名关键字查询"的方式 (FamilyList_Username 表示 Family对象属性中的子属性)
               */
              List findByFamilyList_Username(String usernmae); //根据usernmae属性查询数据
          }
          

          application.properties :

          #配置Redis数据库连接信息/连接参数
          #Redis服务器地址
          spring.redis.host = 127.0.0.1
          #Redis服务器连接端口(默认为6379)
          spring.redis.port=6379
          #Redis服务连接器密码(默认为空)
          spring.redis.password=root
          

          pom.xml :

           4.0.0  org.springframework.boot spring-boot-starter-parent 2.1.3.RELEASE    com.myh chapter_08 0.0.1-SNAPSHOT chapter_08 Demo project for Spring Boot  1.8    org.springframework.boot spring-boot-starter-data-redis   mysql mysql-connector-java 8.0.28   org.springframework.boot spring-boot-starter-test test   org.junit.jupiter junit-jupiter RELEASE test  

          Chapter08ApplicationTests.java :

          package com.myh.chapter_08;
          import com.myh.chapter_08.Repository.Repository.PersonRepository;
          import com.myh.chapter_08.domain.Address;
          import com.myh.chapter_08.domain.Family;
          import com.myh.chapter_08.domain.Person;
          import org.junit.jupiter.api.Test;
          import org.junit.runner.RunWith;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.boot.test.context.SpringBootTest;
          import org.springframework.test.context.junit4.SpringRunner;
          import java.util.ArrayList;
          import java.util.List;
          @RunWith(SpringRunner.class)
          @SpringBootTest
          class Chapter08ApplicationTests { @Autowired
              private PersonRepository personRepository;
              @Test
              public void savePerson() { Person person = new Person("张", "有才");
                  Person person2 = new Person("James", "Harden");
                  //创建并添加地址信息
                  Address address = new Address("北京", "China");
                  person.setAddress(address);
                  //创建并添加家庭成员
                  List list = new ArrayList<>();
                  Family dad = new Family("父亲", "张良");
                  Family mom = new Family("母亲", "李香君");
                  list.add(dad);
                  list.add(mom);
                  person.setFamilyList(list);
                  //向Redis数据库添加数据
                  Person save = personRepository.save(person);
                  Person save2 = personRepository.save(person2);
                  System.out.println(save);
                  System.out.println(save2);
                  System.out.println("向Redis数据库中插入成功");
              }
              @Test
              public void selectPerson() { List list = personRepository.findByAddress_City("北京");
                  System.out.println(list);
              }
              @Test
              public void updatePerson() { Person person = personRepository.findByFirstnameAndLastname("张", "有才").get(0);
                  //修改该对象的属性值
                  person.setLastname("小明");
                  Person update = personRepository.save(person);
                  System.out.println(update);
              }
              @Test
              public void deletePerson() { Person person = personRepository.findByFirstnameAndLastname("张", "小明").get(0);
                  personRepository.delete(person);//删除Redis数据库中的数据
                  System.out.println("删除Redis数据库中的数据成功!");
              }
          }