Spring Boot数据访问

Spring Boot数据访问

Spring Boot数据访问概述

Spring Data是Spring提供了一个用于简化数据库访问、支持云服务的开源框架。它是一个伞形项目,包含了大量关系型数据库及非关系型数据库的数据访问解决方案,其设计目的是使我们可以快速且简单地使用各种数据访问技术。Spring Boot默认采用整合Spring Data地方式统一处理数据访问层,通过添加大量自动配置,引入各种数据访问模板xxxTemplate以及统一的Repository接口,从而达到简化数据访问层的操作。
Spring Data提供了多种类型数据库支持,Spring Boot对Spring Data支持的数据库进行了整合管理,提供了各种依赖启动器。

名称描述
spring-boot-starter-data-jpaSpring Data JPA与Hibernate的启动器
spring-boot-start-data-mongodbMongoDB和Spring Data MongoDB的启动器
spring-boot-start-data-neo4Neo4j图数据库和Spring Data Neo4j的启动器
spring-boot-start-redisRedis键值数据存储与Spring Data Redis和Jedis客户端的启动器

Spring Boot没有提供MyBatis场景依赖,但是MyBatis开发团队自己适配了Spring Boot,提供了mybatis-spring-boot-starter依赖启动器实现数据访问操作。

Spring Boot整合MyBatis

基础环境搭建

因为Spring Boot框架开发很便利,所以实现Spring Boot与数据访问层框架的整合非常简单,主要是引入对应的依赖启动器,并进行数据库相关参数设置即可。
1、数据准备
在MySQL中,创建一个名为springbootdata的数据库,在该数据库中创建两个表t_article和t_comment,并预先插入几条测试数据
springbootdata.sql

create database springbootdata;
use springbootdata;
drop table if exists `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;
insert into `t_article` values ('1','Spring Boot 基础入门','从入门到精通讲解...');
insert into `t_article` values ('2','Spring Cloud基础入门','从入门到精通讲解...');
drop table if exists `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;
insert into `t_comment` values ('1','123','tom1','1');
insert into `t_comment` values ('2','123','tom2','1');
insert into `t_comment` values ('3','123','tom3','1');
insert into `t_comment` values ('4','123','tom4','1');
insert into `t_comment` values ('5','123','tom5','2');

2、创建项目,引入相应的启动器
1)创建Spring Boot项目。创建一个名为chapter03的Spring Boot项目,在Dependencies依赖中选中SQL模块中的Mysql和MyBatis依赖,并根据后续提示完成项目创建。
在这里插入图片描述
2)编写数据库对应的实体类。在chapter03项目中创建名为com.example.chapter03的包,并在该包中编写与数据库表对应的实体类Comment和Article
Comment.java

package com.example.chapter03;

public class Comment {
    private Integer id;
    private String content;
    private String author;
    private Integer aId;
    //省略属性getter和setter方法
    //省略toString()方法
}

Article.java

package com.example.chapter03;

import java.util.List;

public class Article {
    private Integer id;
    private String title;
    private String content;
    private List<Comment> commentList;
    //省略属性getter和setter方法
    //省略toString()方法
}

3、编写配置文件
1)在application.properties配置文件中进行数据库连接配置。
application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456

2)数据源类型选择配置。Spring Boot 1.x版本默认使用的使tomcat.jdbc数据源,Spring Boot 2.x版本默认使用的是hikari数据源。如果使用其他数据源,还需要进行额外配置。
这里选择使用阿里巴巴的Druid数据源。在pom.xml文件中添加Druid数据源启动器。

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

上述引入的依赖druid-spring-boot-starter,同样是阿里巴巴为了迎合Spring Boot项目而适配的Druid数据源启动器,当在pom.xml中引入该启动器后,不需要再进行其他额外配置,Spring Boot项目会自动识别配置Druid数据源。
需要说明的是,上述配置的Druid数据源启动器内部已经初始化了一些运行参数,如果开发过程中需要修改第三方Druid的运行参数,则必须在全局配置文件中修改。
application.properties

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize=20
spring.datasource.minIdle=10
spring.datasource.maxActive=100

修改了Druid数据源的类型、初始化连接数、最小空闲数和最大连接数
注:配置完之后会发现spring.datasource.initialSize、spring.datasource.minIdle、spring.datasource.maxActive属性底纹为黄色,这是因为Spring Boot提供的数据源自动配置类org.springframework.boot.autoconfigure.jdbc.DataSourceProperties中,没有与这些参数对应的默认属性,所以这些设置的属性值无法识别和生效。为此我们需要编写一个自定义配置类,将配置文件中的属性注入到Druid数据源属性中。
在chapter03项目中创建名为com.example.chapter03.config的包,并在该包下创建一个自定义配置类对Druid数据源属性值进行注入
DataSourceConfig.java

package com.example.chapter03.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
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource getDruid(){
        return new DruidDataSource();
    }
}

注:在pom.xml中添加第三方数据源Druid依赖时,本书直接选了适配Spring Boot开发Druid启动器druid-spring-boot-starter,所以可以不需要再进行其他配置,项目就会自动识别该数据源,而有些读者可能会使用独立的Druid依赖文件,这时就必须在全局配置中额外添加"spring.datasource.type=com.alibaba.druid.pool.DruidDataSource"配置,这样项目才能识别配置的Druid数据源。

使用注解的方式整合MyBatis

相比Spring与Mybatis的整合,Spring Boot与MyBatis的整合会使项目开发更加简便,同时还支持XML和注解两种配置方式。
1)创建Mapper接口文件。在chapter03项目中创建名为com.example.chapter03.mapper的包,并在该包下创建一个用于对数据库表t_comment数据操作的接口CommentMapper

package com.example.chapter03.mapper;

import com.example.chapter03.Comment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Repository
@Mapper
public interface CommentMapper {
    @Select("select * from t_comment where id=#{id}")
    public Comment findById(Integer id);
    @Select("insert into t_comment(context,author,a_id)")
    public int insertComment(Comment comment);
    @Select("update t_comment set content=#{content} where id=#{id}")
    public int updataComment(Comment comment);
    @Select("delete from t_comment where id=#{id}")
    public int deleteComment(Integer id);
}

注:这里不进行@Repository注解程序依然可以正确执行,@Mapper可以将CommentMapper注册为Bean,但是开发工具不识别,这里额外使用@Repository可以令开发工具在运行前认为CommentMapper注入了Spring Boot。(和@Repository效果相同的还有,@Service、@Controller 和 @Component。不过它们有各自特殊的作用,这里应当使用 @Repository)

@Mapper注解表示该类是一个MyBatis接口文件,并保证能够被Spring Boot自动扫描到Spring容器中;在该接口内部,分别通过@Select、@Insert、@Update、@Delete注解配合SQL语句完成了对数据库表t_comment数据的增删改查操作。
注:在对应的接口类上添加了@Mapper注解,如果编写的Mapper接口过多时,需要重复为每一个接口文件添加@Mapper注解。为了避免这种麻烦,可以直接在Spring Boot项目启动类上添加@MapperScan(“xxx”)注解,不需要再逐个添加@Mapper注解。@MapperScan(“xxx”)注解的作用和@Mapper注解类似,但是它必须指定需要扫描的具体包名,例如@MapperScan(“com.example.mapper”)。
2)编写单元测试进行接口方法测试。打开chapter03项目的测试类Chapter03ApplicationTest,在该测试类中引入CommentMapper接口,并对接口方法进行测试。
Chapter03ApplicationTest.java

package com.example.chapter03;

import com.example.chapter03.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
    private CommentMapper commentMapper;

    @Test
    public void selectComment(){
        Comment comment=commentMapper.findById(1);
        System.out.println(comment);
    }
}

在这里插入图片描述
查找时aId没有正确输出,这是因为表中的字段a_id被我们在类中映射成了aId,命名法的不同造成了Spring Boot没有正确识别并映射,可以在全局配置文件中添加开启驼峰命名匹配映射。

mybatis.configuration.map-underscore-to-camel-case=true

在这里插入图片描述
可以看到aId正确的输出了。

使用配置文件的方式整合MyBatis

Spring Boot与MyBatis整合使用时,不仅支持注解方式,还支持XML配置文件的方式
1)创建Mapper接口文件。在chapter03项目的com.example.chapter03.mapper包下,创建一个操作t_article数据表的接口ArticleMapper

package com.example.chapter03.mapper;

import com.example.chapter03.Article;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

@Repository
@Mapper
public interface ArticleMapper {
    public Article selectArticle(Integer id);
    public int updateArticle(Article article);
}

2)创建XML映射文件。在chapter03项目的resources目录下,创建一个统一管理映射文件的包mapper,并在该包下编写与ArticleMapper接口对应的映射文件ArticleMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.chapter03.mapper.ArticleMapper">
    <select id="selectArticle" resultMap="articleWithComment">
        select a.*,c.id c_id,c.content c_content,c.author
        from t_article a,t_comment c
        where a.id=c.a_id AND a.id=#{id}
    </select>
    <resultMap id="articleWithComment" type="Article">
        <id property="id" column="id"/>
        <result property="title" column="title"/>
        <collection property="commentList" ofType="Comment">
            <id property="id" column="c_id"/>
            <result property="content" column="c_content"/>
            <result property="author" column="author"/>
        </collection>
    </resultMap>
    <update id="updateArticle" parameterType="Article">
        update t_article
        <set>
            <if test="title != null and title != ''">
                title=#{title},
            </if>
            <if test="content != null and content != ''">
                content=#{content}
            </if>
        </set>

    </update>
</mapper>

<mapper>标签的namespace属性值对应的是ArticleMapper接口文件的全路径名称,在映射文件中根据AritcleMapper接口文件中的方法,编写两个对应的SQL语句;同时配置数据类型映射时,没有使用类的全路径名称,而是是用来类的别名(例如,com.example.chapter03.Article的别名为Article)
关于MyBatis映射文件中的SQL语句具体语法可以查看之前Java Web学习专栏中动态SQL的内容。
3)配置XML映射文件路径。我们在项目中编写的XML映射文件,Spring Boot并无从知晓,所以无法扫描到该自定义编写的XML配置文件,还需要在全局配置文件中添加MyBatis映射文件路径的配置,同时需要添加实体类别名映射路径。

mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.example.chapter03

4)编写单元测试类。打开项目的测试类Chapter03ApplicationTests

package com.example.chapter03;

import com.example.chapter03.mapper.ArticleMapper;
import com.example.chapter03.mapper.CommentMapper;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Chapter03ApplicationTests {

    @Autowired
    private CommentMapper commentMapper;

    public void selectComment(){
        Comment comment=commentMapper.findById(1);
        System.out.println(comment);
    }

    @Autowired
    private ArticleMapper articleMapper;
    @Test
    public void selectArticle(){
        Article article=articleMapper.selectArticle(1);
        System.out.println(article);
    }
}

在这里插入图片描述

Spring Boot整合JPA

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

Spring Data JPA介绍

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

编写ORM实体类

引入相关包

        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

Spring Data JPA框架是针对具有ORM关系的数据进行操作,所以在使用Spring Data JPA时,首先需要编写一个实体类与数据表进行映射,并且配置好映射关系

package com.example.chapter03;

import javax.persistence.*;

@Entity(name = "t_comment")
public class Discuss {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "a_id")
    private Integer aId;
    //省略getXXX()和setXXX()
}

上述代码定义了一个Spring Data JPA 实体类Discuss,并将该类与数据表t_comment进行映射。
1)@Entity:标注要与数据库做映射的实体类,默认情况下,数据表的名称就是首字母小写的类名。当然,还可以使用name属性指定映射的表名。
2)@Id:标注在类属性或者getter方法上,表示某一个属性对应表中的主键。
3)@GeneratedValue:与@Id注解标注在同一位置,用于表示属性对应主键的生成策略,可省略。Spring Data JPA支持的主键生成策略包括有TABLE(使用一个特定的数据库表格来保存主键)、SEQUENCE(不支持主键自增长的数据库主键生成策略)、IDENTITY(主键自增)和AUTO(JPA自主选择前面三种合适的策略,默认选项)。

编写Repository接口

下面我们针对不同的表数据操作编写各自对应的Repository接口,并根据需要编写对应的数据操作方法

package com.example.chapter03;

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.awt.print.Pageable;
import java.util.List;

public interface DiscussRepository extends JpaRepository<Discuss,Integer> {
    public List<Discuss> findByAutorNotNull();
    @Query("select c from t_comment c where c.aId = ?1")
    public List<Discuss> getDiscussPaged(Integer aid, Pageable pageable);
    @Query(value = "select * from t_comment where a_Id = ?1",nativeQuery = true)
    public List<Discuss> getDiscussPaged2(Integer aid,Pageable pageable);
    @Transactional
    @Modifying
    @Query("update t_comment c set c.author = ?1 where c.id = ?2")
    public int updateDiscuss(String author,Integer id);
    @Transactional
    @Modifying
    @Query("delete t_comment c where c.id = ?1")
    public int deleteDiscuss(Integer id);
}

1)findByAuthorNotNull()方法:该方法是一个基本的查询方法,上方没有任何注释,属于JPA支持的方法名关键字查询方式;同时通过定义的方法名可以猜测出,该方法的作用是查询author非空的Discuss评论信息。
2)getDiscussPaged()方法:该方法上方通过@Query注解引入了一个SQL语句,用于通过文章分页ID查询Discuss评论信息。
3)getDiscussPaged2()方法:该方法的功能与getDiscussPaged()基本类似,区别是该方法上方的@Query注解将nativeQuery属性设置为true,用来编写原生SQL语句。
4)updateDiscuss()方法和deleteDiscuss()方法:这两个方法同样使用@Query注解配置了对应的SQL语句,这两个方法分别对应数据的更新和删除操作;需要说明的是,数据更新或者删除操作的方法上还使用了@Modifying和@Transactional注解,其中,@Modifying表示支持数据变更,@Transactional表示支持事务管理。

1)使用Spring Data JPA自定义Repository接口,必须继承XXRepository<T,ID>接口,其中的T代表要操作的实体类,ID代表实体类主键数据类型。

  • Repository是Spring Data JPA提供的用于自定义Reposity接口的顶级父接口,该接口中没有声明任何方法。
  • CrudRepository接口是Repository的继承接口之一,包含了一些基本的CRUD方法。
  • PagingAndSortingRepository接口继承CrudRepository接口的同时,提供了分页和排序两个方法。
  • QueryByExampleExecutor接口是进行条件封装查询的顶级父接口,允许通过Example实例执行复杂条件查询。

JpaRepository接口同时继承了PagingAndSortingRepository接口和QueryByExampleExecutor接口,并额外提供了一些数据操作方法。自定义Repository接口文件时,通常会直接选择JpaRepository接口。
2)在使用Spring Data JPA进行数据操作时,可以有多种实现方式,主要方式

  • 如果自定义接口继承了JpaRepository接口,则默认包含了一些常用的CRUD方法。
  • 自定义Repository接口中,可以使用@Query注解配合SQL语句进行数据的查、改、删操作。
  • 自定义Repository接口中,可以直接使用方法名关键字进行查询操作。
    其中,Spring Data JPA中支持的方法名关键字及对应的SQL片段说明。
关键字方法名示例对应的SQL片段
AndfindByLastnameAndFirstnamewhere x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstnamewhere x.lastname = ?1 or x.firstname = ?2
Is,EqualsfindByFirstname,findByFirstnameIs,findByFirstnameEqualswhere x.firstname = ?1
BetweenfindByStartDateBetweenwhere x.startDate between ?1 and ?2
LessThanfindByAgeLessThanwhere x.age < ?1
LessThanEqualfindByAgeLessThanEqualwhere x.age <= ?1
GreaterThanfindByAgeGreaterThanwhere x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqualwhere x.age >= ?1
AfterfindByStartDateAfterwhere x.startDate > ?1
BeforefindByStartDateBeforewhere x.startDate < ?1
IsNullfindByAgeIsNullwhere x.age is null
IsNotNull,NotNullfindByAge(Is)NotNullwhere x.age not null
LikefindByFirstnameLikewhere x.firstname like ?1
NotLikefindByFirstnameNotLikewhere x.firstname not like ?1
StartingWithfindByFirstnameStartingWithwhere x.firstname like ?1 (parameter bound with appended %)
EndingWithfindByFirstnameEndingWithwhere x.firstname like ?1 (parameter bound with prepended%)
ContainingfindByFirstnameContainingwhere x.firstname like ?1 (parameter bound wrapped in %)
OrderByfindByAgeOrderByLastnameDescwhere x.age = ?1 order by x.lastname desc
NotfindByLastnameNotwhere x.lastname <> ?1
InfindByAgeIn(Collection<Age> ages)where x.age in ?1
NotInfindByAgeNotIn(Collection<Age> ages)where x.age not in ?1
TruefindByActiveTrue()where x.active = true
FalsefindByActiveFalse()where x.active = false
IgnoreCasefindByFirstnameIgnoreCasewhere UPPER(x.firstame) = UPPER(?1)

3)在自定义的Repository接口中,针对数据的变更操作(修改、删除),无论是否是用了@Query注解,都必须在方法上方添加@Transactional注解进行事务管理,否则程序执行就会出现InvalidDataAccessApiUsageException异常。如果在调用Repository接口方法的业务层Service类上已经添加了@Transactional注解进行事务管理,那么Repository接口文件中就可以省略@Transactional注解。
4)在自定义的Repository接口中,使用@Query注解方式执行数据变更操作(修改、删除),除了要使用@Query注解,还必须添加@Modifying注解表示数据变更。
5)JPA还支持使用Example实例进行负责条件查询。例如,针对JpaRepository接口中已存在的findAll(Example<S> var1)方法进行查询

        //用example精确匹配查询条件
        Discuss discuss=new Discuss();
        discuss.setAuthor("123");
        Example<Discuss> example=Example.of(discuss);
        List<Discuss> list=repository.findAll(example);
        //用exampleMatcher模糊匹配查询条件
        Discuss discuss1=new Discuss();
        discuss.setAuthor("1");
        ExampleMatcher matcher=ExampleMatcher.matching().withMatcher("author",startsWith());
        Example<Discuss> example1=Example.of(discuss,matcher);
        List<Discuss> list=repository.findAll(example);

使用Spring Boot整合JPA

1)添加Spring Data JPA依赖启动器。在项目的pom.xml文件中添加Spring Data JPA依赖启动器。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

上述代码中,并没有编写Spring Data JPA对应的版本号,这是因为Spring Boot对Spring Data JPA的版本号进行了统一管理。
2)编写ORM实体类。为了方便操作,我们以之前创建的数据库表t_comment为例编写对应的实体类,将之前创建的Comment类复制一份并重命名为Discuss
Discuss.java

package com.example.chapter03;

import javax.persistence.*;

@Entity(name = "t_comment")
public class Discuss {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String author;
    private String content;
    @Column(name = "a_id")
    private Integer aId;
    //省略getXXX()和setXXX()方法
    //省略toString()方法
}

3)编写Repository接口。在chapter03项目中创建名为com.example.chapter03.repository的包,该包下创建一个用于对数据库表t_comment进行操作的Repository接口DiscussRepository。

package com.example.chapter03.repository;

import com.example.chapter03.Discuss;
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.awt.print.Pageable;
import java.util.List;

public interface DiscussRepository extends JpaRepository<Discuss,Integer> {
    public List<Discuss> findByAutorNotNull();
    @Query("select c from t_comment c where c.aId = ?1")
    public List<Discuss> getDiscussPaged(Integer aid, Pageable pageable);
    @Query(value = "select * from t_comment where a_Id = ?1",nativeQuery = true)
    public List<Discuss> getDiscussPaged2(Integer aid,Pageable pageable);
    @Transactional
    @Modifying
    @Query("update t_comment c set c.author = ?1 where c.id = ?2")
    public int updateDiscuss(String author,Integer id);
    @Transactional
    @Modifying
    @Query("delete t_comment c where c.id = ?1")
    public int deleteDiscuss(Integer id);
}

自定义一个DiscussRepository接口文件,并编写了对数据表t_comment进行查、改、删操作的方法。
4)编写单元测试进行接口方法测试。将Chapter03ApplicationTests测试类在当前位置复制一份并重命名为JpaTests,用来编写Jpa相关的单元测试,并对内容稍微修改后编写DiscussRepository接口对应的测试方法。

	@Autowired
    private DiscussRepository repository;
    //使用JpaRepository内部方法进行数据操作
    @Test
    public void selectComment(){
        Optional<Discuss> optional=repository.findById(1);
        if(optional.isPresent()){
            System.out.println(optional.get());
        }
    }

在这里插入图片描述

    @Test
    public void selectCommentByKeys(){
        List<Discuss> list=repository.findByAuthorNotNull();
        System.out.println(list);
    }

在这里插入图片描述

    @Test
    public void selectCommentPaged(){
        Pageable pageable= PageRequest.of(0,3);
        List<Discuss> allPaged = repository.getDiscussPaged(1,pageable);
        System.out.println(allPaged);
    }

在这里插入图片描述

    //使用Example封装参数进行数据查询操作
    @Test
    public void selectCommentByExample(){
        Discuss discuss=new Discuss();
        discuss.setAuthor("tom1");
        Example<Discuss> example=Example.of(discuss);
        List<Discuss> list=repository.findAll(example);
        System.out.println(list);
    }

在这里插入图片描述

    @Test
    public void selectCommentByExampleMatcher(){
        Discuss discuss=new Discuss();
        discuss.setAuthor("tom");
        ExampleMatcher matcher=ExampleMatcher.matching().withMatcher("author",startsWith());
        Example<Discuss> example=Example.of(discuss,matcher);
        List<Discuss> list=repository.findAll(example);
        System.out.println(list);
    }

在这里插入图片描述

Spring Boot整合Redis

Redis介绍

Redis是一个开源(BSD许可)的、内存中数据结构存储系统,它可以用作数据库、缓存和消息中间件,并提供多种语言的API。Redis支持多种类型的数据结构,例如字符串(String)、散列(hashes)、列表(lists)、集合(sets)等。同时,Redis内部内置了复本(replication)、LUA脚本(Lua scripting)、LRU驱动事件(LRU eviction)、事务(Transaction) 和不同级别的磁盘持久化(persistence),并通过Redis Sentinel和自动分区提供高可用性(high avaliability)。
相较于其他的key-value键值存储系统而言,Redis主要有以下优点。
1)存放速度快LRedis速度非常快,每秒可执行大约110 000次的设置操作,或者执行81 000次的读取操作。
2)支持丰富的数据类型:Redis支持开发人员常用的大多数数据类型,例如列表、集合、排序集和散列等。
3)操作具有原子性:所有Redis操作都是原子操作,这确保如果两个客户端并发访问,Redis服务器能接受更新后的值。
4)提供多种功能:Redis提供了多种功能特性,可用作非关系型数据库、缓存中间件、消息中间件等。

Redis下载安装

使用非关系型数据库Redis,必须先进行安装配置并开启Redis服务器,然后使用对应客户端连接使用。Redis支持多种方式的安装配置,例如Windows、Linux系统安装,Docker镜像安装等,不同安装方式的安装过程也不相同。为了方便操作,此处选择在Windows平台下进行Redis安装。
限制GitHub上下载Windows平台下的Redis安装包,在下载列表中找到对应版本的Redis,并选择对应的安装包下载即可。
Redis3.2.100下载地址
这里使用的是Redis3.2.100版本(当前Spring Boot 2.1.3版本与Redis进行了自动化配置,需要使用Redis 3.2及以上版本进行使用连接)。

Redis服务开启与连接配置

完成Redis的下载安装后,启动Redis服务,并使用可视化客户端工具连接对应的Redis服务进行效果测试
1)开启Redis服务
先进入到Redis安装包的解压目录,其对应目录文件内容
在这里插入图片描述
解压过后会有多个目录文件,包括两个可执行文件:

  • redis-cli.exe 用于开启客户端工具
  • redis-server.exe 用于开启redis服务
    这里双击redis-server.exe指令即可开启Redis服务

在这里插入图片描述
从图中可以看出,Redis服务正常启动,同时在终端窗口显示了当前Redis版本为3.2.100和默认启动端口号为6379.
2)Redis可视化客户端工具安装连接
Redis解压目录下的redis-cli.exe指令用于开启客户端工具,不过双击这个指令打开的是终端操作界面,对于Redis的可视化操作和查看并不方便。这里推荐使用一个Redis客户端可视化管理工具Redis Desktop Manage连接服务进行管理

使用Spring Boot整合Redis

我们对Redis进行了简单介绍,并完成了Redis服务的安装配置,接下来重点讲解Spring Boot与Redis的整合使用
1)添加Spring Data Redis依赖启动器。先在项目的pom.xml文件中添加Redis依赖启动器。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

上述添加的Redis依赖启动器代码中,也没有编写对应的版本号信号,这是因为Spring Boot为Redis实现了自动配置,所以会统一管理版本号信息。
2)编写实体类。此处为了延时Spring Boot与Redis数据库的整合使用,在chapter03项目的com.example.chapter03包下编写几个对应的实体类。
Person.java

package com.example.chapter03;

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("persons")
public class Person {
    @Id
    private String id;
    @Indexed
    private String lastname;
    private Address address;
    private List<Family> familyList;
    //省略getter和setter
    //省略有参和无参构造方法
    //省略toString()方法
}

Address.java

package com.example.chapter03;

import org.springframework.data.redis.core.index.Indexed;

public class Address {
    @Indexed
    private String city;
    @Indexed
    private String country;
    //省略getter和setter
    //省略有参和无参构造方法
    //省略toString()方法
}

Family.java

package com.example.chapter03;

import org.springframework.data.redis.core.index.Indexed;

public class Family {
    @Indexed
    private String type;
    @Indexed
    private String username;
    //省略getter和setter
    //省略有参和无参构造方法
    //省略toString()方法
}

@RedisHash(“persons”):用于指定操作实体类对象在Redis数据库中的存储空间,此处表示针对Person实体类的数据操作都存储在Redis数据库中名为persons的存储空间下。
@Id:用于标识实体类主键。在Redis数据库中会默认生成字符串形式的HashKey表示唯一的实体对象id,当然也可以在数据存储时手动指定id。
@indexed:用于标记对应属性在Redis数据库中生成二级索引。使用该注解后会在Redis数据库中生成属性对应的二级索引,索引名称就是属性名,可以方便地进行数据条件查询。
3)编写Repository接口。Spring Boot针对包括Redis在内地一些常用数据库提供了自动化配置,可以通过实现Repository接口简化对数据库中地数据进行地增删改查操作,这些操作方法通Spring Data JPA操作数据地使用方法基本相同,可以使用方法名关键字进行数据操作。这里我们在com.example.chapter03.repository包下创建操作Person实体类的PersonRepository接口
PersonRepository.java

package com.example.chapter03.repository;

import com.example.chapter03.Person;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface PersonRepository extends CrudRepository<Person,String> {
    List<Person> findByLastname(String lastname);
    Page<Person> findPersonByLastname(String lastname, Pageable page);
    List<Person> findByFirstnameAndLastname(String firstname,Pageable pageable);
    List<Person> findByAddress_City(String city);
    List<Person> findByFamilyList_Username(String username);
}

PersonRepository接口继承自CrudRepositoty接口,该接口定义了若干查询方法。
需要说明的是,在操作Redis数据库时编写的Repository接口文件需要继承CrudRepository接口,而不是继承JpaRepository,这是因为JpaRepository是Spring Boot整合JPA特有的。当然,也可以在项目pom.xml文件中同时导入Spring Boot整合的JPA依赖和Redis依赖,这样就可以编写一个继承JpaRepository的接口操作数据库了。
4)Redis数据库连接配置。在项目的全局配置文件application.properties中添加Redis数据库的连接配置。

spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=

上述代码中,在Spring Boot项目的全局配置文件application.properties中额外添加了Redis数据库的相关配置信息。
注:上述配置中如果不进行配置,则使用默认配置localhost:6379
5)编写单元测试进行接口方法测试。将Chapter03ApplicationTests测试类在当前位置复制一份并重命名为RedisTests,并对内容稍稍修改后编写PersonRepository接口对应的测试方法。

    @Autowired
    private PersonRepository repository;
    @Test
    public void savePerson(){
        Person person=new Person("张","有才");
        Person person2=new Person("James","Harden");
        Address address=new Address("北京","China");
        person.setAddress(address);
        List<Family> list=new ArrayList<>();
        Family dad=new Family("父亲","张三");
        Family mom=new Family("母亲","李四");
        list.add(dad);
        list.add(mom);
        person.setFamilyList(list);
        Person save=repository.save(person);
        Person save2=repository.save(person2);
        System.out.println(save);
        System.out.println(save2);
    }

在这里插入图片描述
在这里插入图片描述

    @Test
    public void selectPerson(){
        List<Person> list=repository.findByAddress_City("北京");
        System.out.println(list);
    }

在这里插入图片描述

    @Test
    public void updatePerson(){
        Person person=repository.findByFirstnameAndLastname("张","有才").get(0);
        person.setLastname("小明");
        Person update=repository.save(person);
        System.out.println(update);
    }

在这里插入图片描述
在这里插入图片描述

    @Test
    public void deletePerson(){
        Person person=repository.findByFirstnameAndLastname("张","小明").get(0);
        repository.delete(person);
    }

在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值