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 Web
、Lombok
我们再添加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;
}
}
- 使用
@Table
注解映射数据库的表,注意@Table
所在的包; - 使用
@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客户端
这里的控制器PersonController
和ControllerClient
和上例保持一致,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());
}
}
- 自动配置已经为我们配置了
DatabaseClient
的Bean,我们可以直接注入; - 读取
schema.sql
中的sql语句; - 我们可以使用
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)
多谢大家支持。