反应式数据库驱动规范R2DBC小试牛刀

来源:这里教程网 时间:2026-03-01 15:14:50 作者:

1. 简介

三月份已经介绍过 R2DBC ,它是一种异步的、非阻塞的关系式数据库连接规范。尽管一些 NoSQL 数据库供应商为其数据库提供了反应式数据库客户端,但对于大多数项目而言,迁移到 NoSQL 并不是一个理想的选择。这促使了一个通用的响应式关系数据库连接规范的诞生。 作为拥有庞大用户群的关系式数据库 MySQL 也有了反应式驱动,不过并不是官方的。但是 Spring 官方将其纳入了依赖池,说明该类库的质量并不低。所以今天就尝尝鲜,试一下使用 R2DBC 连接 MySQL

2. 环境依赖

基于 Spring Boot 2.3.1 Spring Data R2DBC ,还有反应式Web框架 Webflux ,同时也要依赖 r2dbc-mysql 库,所有的 Maven 依赖为:

       
<!--r2dbc mysql 库-->

        
<
dependency
>

            
<
groupId
>dev.miku
</
groupId
>

            
<
artifactId
>r2dbc-mysql
</
artifactId
>

        
</
dependency
>

        
<!--Spring r2dbc 抽象层-->

        
<
dependency
>

            
<
groupId
>org.springframework.boot
</
groupId
>

            
<
artifactId
>spring-boot-starter-data-r2dbc
</
artifactId
>

        
</
dependency
>

        
<!--自动配置需要引入的一个嵌入式数据库类型对象-->

        
<
dependency
>

            
<
groupId
>org.springframework.boot
</
groupId
>

            
<
artifactId
>spring-boot-starter-data-jdbc
</
artifactId
>

        
</
dependency
>

       
<!--反应式web框架-->

        
<
dependency
>

            
<
groupId
>org.springframework.boot
</
groupId
>

            
<
artifactId
>spring-boot-starter-webflux
</
artifactId
>

        
</
dependency
>

MySQL 版本为5.7,没有测试其它版本。

3. R2DBC配置

所有的 R2DBC 自动配置都在 org.springframework.boot.autoconfigure.data.r2dbc 包下,如果要配置 MySQL 必须针对性的配置对应的连接工厂接口 ConnectionFactory ,当然也可以通过 application.yml 配置。个人比较喜欢 JavaConfig


@Bean


ConnectionFactory 
connectionFactory() {

    
return 
MySqlConnectionFactory.
from(
MySqlConnectionConfiguration.
builder()

            .
host(
"127.0.0.1")

            .
port(
3306)

            .
username(
"root")

            .
password(
"123456")

            .
database(
"database_name")

             
// 额外的其它非必选参数省略                          

            .
build());

}

详细配置可参考 r2dbc-mysql 的官方说明: https://github.com/mirromutth/r2dbc-mysql

ConnectionFactory 配置好后,就会被注入 DatabaseClient 对象。该对象是非阻塞的,用于执行数据库反应性客户端调用与反应流背压请求。我们可以通过该接口反应式地操作数据库。

4. 编写反应式接口

我们先创建一张表并写入一些数据:


create 
table client_user

(

    user_id         
varchar(
64)                              
not 
null comment 
'用户唯一标示' primary key,

    username        
varchar(
64)                              
null comment 
'名称',

    phone_number    
varchar(
64)                              
null comment 
'手机号',

    gender          
tinyint(
1) default 
0                     
null comment 
'0 未知 1 男 2 女  '

)

对应的实体为:


package 
cn.
felord.
r2dbc.
config;





import 
lombok.
Data;





/**

 
* @author felord.cn

 
*/


@Data


public 
class 
ClientUser {




    
private 
String 
userId;

    
private 
String 
username;

    
private 
String 
phoneNumber;

    
private 
Integer 
gender;

}

然后我们编写一个 Webflux 的反应式接口:


package 
cn.
felord.
r2dbc.
config;





import 
org.
springframework.
data.
r2dbc.
core.
DatabaseClient;


import 
org.
springframework.
web.
bind.
annotation.
GetMapping;


import 
org.
springframework.
web.
bind.
annotation.
RequestMapping;


import 
org.
springframework.
web.
bind.
annotation.
RestController;


import 
reactor.
core.
publisher.
Flux;


import 
reactor.
core.
publisher.
Mono;





import 
javax.
annotation.
Resource;





/**

 
* The type User controller.

 
*

 
* @author felord.cn

 
* @since 17 :07

 
*/


@RestController


@RequestMapping(
"/user")


public 
class 
UserController {

    
@Resource

    
private 
DatabaseClient 
databaseClient;




    
/**

     
* 查询

     
*

     
* @return 返回Flux序列 包含所有的ClientUser

     
*/

    
@GetMapping(
"/get")

    
public 
Flux
<
ClientUser
> 
clientUserFlux() {

        
return 
databaseClient.
execute(
"select * from client_user").
as(
ClientUser.
class)

                .
fetch()

                .
all();

    }




    
/**

     
* 响应式写入.

     
*

     
* @return Mono对象包含更新成功的条数

     
*/

    
@GetMapping(
"/add")

    
public 
Mono
<
Integer
> 
insert() {

        
ClientUser 
clientUser 
= 
new 
ClientUser();

        
clientUser.
setUserId(
"34345514644");

        
clientUser.
setUsername(
"felord.cn");

        
clientUser.
setPhoneNumber(
"3456121");

        
clientUser.
setGender(
1);




        
return 
databaseClient.
insert().
into(
ClientUser.
class)

                .
using(
clientUser)

                .
fetch().
rowsUpdated();

    }




}

调用接口就能获取到期望的数据结果。

5. 总结

乍一看 R2DBC 并没有想象中的那么难,但是间接的需要了解 Flux Mono 等抽象概念。同时目前来说如果不和 Webflux 框架配合也没有使用场景。就本文的 MySQL 而言, R2DBC 驱动还是社区维护(不得不说 PgSQL 就做的很好)。

然而需要你看清的是 反应式才是未来 。如果你要抓住未来就需要现在就了解一些相关的知识。这让我想起五年前刚刚接触 Spring Boot 的感觉。另外这里有一份 Spring 官方关于 R2DBC 的PPT,也是让你更好了解 R2DBC 的权威资料。可以关注: 码农小胖哥 回复 r2dbc 获取。

相关推荐