Spring Boot 2.x实战90 - 响应式编程5 - Reactive 关系型数据库(R2DBC)

4. Reactive关系型数据库-R2DBC

与关系型数据库进行交互的JDBC不具备与数据库异步交互的能力,R2DBC(Reactive Relational Database Connectivity)将响应式编程API带给关系型SQL数据库。

Spring Data R2DBC为此提供支持,同样Spring Boot也提供了starter:spring-boot-starter-data-r2dbc和自动配置:spring-boot-actuator-autoconfigure-r2dbc

在本书编写的时候,R2DBC还在试验阶段,第一个正式版还没有发布;在正式版发布之后,Group(org.springframework.boot.experimental)和版本信息应该会有变化。

新建应用,信息如下:

Group:top.wisely

Artifact:learning-reactive-sql

Dependencies:Spring Reactive WebLombok

我们再添加R2DBC相关依赖,具体依赖如下:

repositories {
	mavenCentral()
	maven { url 'https://repo.spring.io/snapshot' }
	maven { url 'https://repo.spring.io/milestone' }
}
dependencyManagement {
	imports {
		mavenBom("org.springframework.boot.experimental:spring-boot-dependencies-r2dbc:0.1.0.BUILD-SNAPSHOT") //Group和版本会有变化
	}
}
dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-web'
   implementation 'org.springframework.boot.experimental:spring-boot-starter-data-r2dbc'
   implementation 'org.springframework.boot.experimental:spring-boot-actuator-autoconfigure-r2dbc'
   implementation 'io.r2dbc:r2dbc-postgresql' //Postgresql的R2DBC驱动
   implementation 'io.r2dbc:r2dbc-pool' // 数据库连接池
	 implementation 'io.r2dbc:r2dbc-client' // R2DBC客户端
   compileOnly 'org.projectlombok:lombok'
  //...
}

本节使用Postgresql数据库作为演示。

4.1 安装Postgresql

使用docker compose安装MongoDb。

stack.yml

version: '3.1'

services:
  db:
    image: postgres
    restart: always
    ports:
      - 5432:5432
    environment:
      POSTGRES_DB: first_db
      POSTGRES_USER: wisely
      POSTGRES_PASSWORD: zzzzzz

执行命令:

$ docker-compose -f stack.yml up -d

4.2 Spring Boot自动配置

Spring Boot提供的自动配置在spring-boot-actuator-autoconfigure-r2dbc包中,主要有:

  • ConnectionFactoryAutoConfiguration:基于连接池的connectionFactory Bean的配置;使用R2dbcProperties通过spring.r2dbc.*进行配置。
    • 数据库连接配置:spring.r2dbc.url
    • 连接池配置:spring.r2dbc.pool.*
  • R2dbcDataAutoConfiguration:自动配置数据库客户端DatabaseClient的Bean,类似于JdbcTemplate,可以直接进行查询:
  • R2dbcRepositoriesAutoConfiguration:使用@EnableR2dbcRepositories开启Spring Data R2DBC Repository的支持;
  • R2dbcTransactionManagerAutoConfiguration:自动配置事务管理器R2dbcTransactionManager的Bean,这样我们可以使用注解@Transactional进行声明式事务处理了。
  • ReactiveTransactionAutoConfiguration:注册TransactionalOperator的Bean来简化处理编程式事务处理。

4.3 示例

我们使用起Spring Data R2DBC和其它的Spring Data项目几乎是相同的,我们来一步一步的学习:

4.3.1 连接数据库

通过application.yml中配置连接数据库:

spring:
  r2dbc:
    url: r2dbc:postgresql://localhost:5432/first_db
    username: wisely
    password: zzzzzz
4.3.2 定义领域模型
//...
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Table;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Table("person") //1
public class Person {
    @Id
    private Long id;
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
}    
  1. 使用@Table注解映射数据库的表,注意@Table所在的包;
  2. 使用@Id注解映射数据库的主键。
4.3.3 定义Repository
public interface PersonRepository extends R2dbcRepository<Person, Long> {
    @Query("select id, name, age  from person")
    Flux<Person> findAll();
}

在这里我们继承的接口是R2dbcRepository;和其它的Spring Data一样,这里演示用自定义的方法覆盖了默认的findAll()方法

4.3.4 定义控制器和WebClient客户端

这里的控制器PersonControllerControllerClient和上例保持一致,ControllerClient代码id修改为Long类型。

@Component
public class ControllerClient {
  //...
    public Long add1(){//返回值为Long
      //...
    }
  //...
    public void delete(Long id){ //入参为Long
      //...
    }

}
4.3.5 初始化数据库

使用schema.sql用来建立Person对应的表:

create table if not exists person (
  id serial primary key,
  name varchar(255) not null,
  age int4 not null
);

但目前Spring Data R2DBC不支持自动读取schema.sql,我们编写数据库初始化代码读取语句执行:

@Component
public class ReactiveDatabaseInitializer {

    private final DatabaseClient client;

    private final String sql;

    public ReactiveDatabaseInitializer(DatabaseClient client, //1
                                       @Value("classpath:schema.sql") Resource resource) throws Exception{
        this.client = client;
        try (Reader in = new InputStreamReader(resource.getInputStream())) {
            this.sql = FileCopyUtils.copyToString(in); //2
        }
    }

    public Mono<Void> initialize () {
        return client.execute().sql(this.sql).then() //3
                .onErrorResume(throwable -> Mono.empty());
    }

}
  1. 自动配置已经为我们配置了DatabaseClient的Bean,我们可以直接注入;
  2. 读取schema.sql中的sql语句;
  3. 我们可以使用DatabaseClient执行sql语句。
4.3.6 启动验证

CommandLineRunner中启动初始化数据库和执行WebClient

@Bean
CommandLineRunner webClientClr(ControllerClient controllerClient,
                        ReactiveDatabaseInitializer initializer){
   return args -> {
      initializer.initialize().block();
      Long id = controllerClient.add1();
      controllerClient.add2();
      Thread.sleep(1000);
      controllerClient.list();
      Thread.sleep(1000);
      controllerClient.delete(id);
      Thread.sleep(1000);
      controllerClient.list();
   };
}

应用启动的结果:
在这里插入图片描述

新书推荐:

我的新书《从企业级开发到云原生微服务:Spring Boot 实战》已出版,内容涵盖了丰富Spring Boot开发的相关知识
购买地址:https://item.jd.com/12760084.html
在这里插入图片描述

主要包含目录有:

第一章 初识Spring Boot(快速领略Spring Boot的美丽)
第二章 开发必备工具(对常用开发工具进行介绍:包含IntelliJ IDEA、Gradle、Lombok、Docker等)
第三章 函数式编程
第四章 Spring 5.x基础(以Spring 5.2.x为基础)
第五章 深入Spring Boot(以Spring Boot 2.2.x为基础)
第六章 Spring Web MVC
第七章 数据访问(包含Spring Data JPA、Spring Data Elasticsearch和数据缓存)
第八章 安全控制(包含Spring Security和OAuth2)
第九章 响应式编程(包含Project Reactor、Spring WebFlux、Reactive NoSQL、R2DBC、Reactive Spring Security)
第十章 事件驱动(包含JMS、RabbitMQ、Kafka、Websocket、RSocket)
第11章 系统集成和批处理(包含Spring Integration和Spring Batch)
第12章 Spring Cloud与微服务
第13章 Kubernetes与微服务(包含Kubernetes、Helm、Jenkins、Istio)
多谢大家支持。

猜你喜欢

转载自blog.csdn.net/wiselyman/article/details/107173150