Spring 核心技术解析【纯干货版】- XII:Spring 数据访问模块 Spring-R2dbc 模块精讲

server/2025/3/1 3:58:43/

在现代应用架构中,高并发、低延迟的需求推动了 响应式编程 的发展,而传统的 JDBC 由于其 同步阻塞 机制,在高吞吐场景下可能成为瓶颈。R2DBC(Reactive Relational Database Connectivity) 作为 响应式关系型数据库访问标准,正是为了解决这一问题而诞生的。

Spring R2DBC 作为 Spring 生态 对 R2DBC 的封装,提供了 非阻塞、异步的数据库访问能力,并与 Spring WebFlux 深度集成,使得在 Spring 应用中开发 响应式数据库访问 变得更加简单高效。本篇文章将深入解析 Spring R2DBC 模块的核心技术,包括 基本概念、关键特性、组件解析、数据库操作示例,以及 R2DBC 与 JDBC 的对比,帮助开发者更好地理解和应用这一技术。

无论你是正在构建 高性能 WebFlux 应用,还是希望探索 响应式数据库访问的可能性,本篇文章都将为你提供实用的技术指导和最佳实践。


文章目录
      • 1、Spring-R2dbc 模块介绍
        • 1.1、Spring-R2dbc 模块概述
        • 1.2、Spring-R2dbc 模块依赖
        • 1.3、Spring-R2dbc 模块作用
      • 2、R2DBC介绍
        • 2.1、为什么需要 R2DBC?
        • 2.2、R2DBC 关键特性
        • 2.3、R2DBC 与 JDBC 的对比
        • 2.4、R2DBC 主要组件
      • 3、Spring R2DBC 进行数据库操作的示例
        • 3.1、添加依赖
        • 3.2、配置 R2DBC 数据源
        • 3.3、创建数据库模型
        • 3.4、创建 `DatabaseClient` 进行数据库操作
        • 3.5、使用事务管理
        • 3.6、测试 R2DBC 代码
      • 4、R2DBC 通常使用 PostgreSQL,而不是 MySQL
      • X、后记

1、Spring-R2dbc 模块介绍
1.1、Spring-R2dbc 模块概述

Spring R2DBC 模块,是 Spring 生态系统中用于支持反应式编程模型与关系型数据库交互的一个模块

R2DBC(Reactive Relational Database Connectivity)是一个基于 Reactive Streams 规范的异步、非阻塞的数据库访问技术,它旨在为现代应用程序提供高性能的数据访问能力,特别是在需要高吞吐量和低延迟的场景下。

1.2、Spring-R2dbc 模块依赖

Spring-Tx 模块的依赖有五个,分别是同为 Spring 模块的 Spring-Beans、Spring-Core 模块以及 SPring-Tx 模块。r2dbc-spi reactor-core

其中 Spring Beans 模块是对 Spring Bean 进行定义,实现 IOC 基础功能的模块。Spring-Core 是 Spring 中的基础模块,它提供了框架运行所必需的核心功能。而 Spring Tx 模块,是 Spring 中处理事务管理的模块。

r2dbc-spi 提供了反应式数据库访问的标准接口,而reactor-core提供了实现这些接口所需的反应式编程工具。

1.3、Spring-R2dbc 模块作用

Spring R2DBC 是 Spring 对 R2DBC(Reactive Relational Database Connectivity)的封装,用于在 Spring 响应式环境(如 WebFlux) 下进行 非阻塞、异步的数据库操作,替代传统 JDBC 的同步方式。

主要作用:

  1. 提供响应式数据库访问:基于 R2DBC,实现 非阻塞、异步 数据操作。
  2. 封装底层 API:通过 DatabaseClient 提供类似 JdbcTemplate 的便捷操作方式。
  3. 支持事务管理:提供 R2dbcTransactionManager,实现 响应式事务管理。
  4. 集成 Spring Data:支持 Spring Data R2DBC,提供 响应式 Repository 方案。
  5. 兼容 WebFlux:与 Spring WebFlux 无缝集成,适用于 高并发、低延迟 场景。

Spring R2DBC 适用于 需要高吞吐、低延迟的响应式应用,但不适用于 传统阻塞式架构。


2、R2DBC介绍

R2DBC(Reactive Relational Database Connectivity)是 面向关系数据库的响应式编程 API,用于替代传统的 JDBC,以 非阻塞、异步 的方式访问数据库。它特别适用于 高并发、低延迟 的应用,比如 WebFlux 或其他响应式架构。

2.1、为什么需要 R2DBC?

在 Spring 传统的 JDBC 访问中,数据库连接是 同步阻塞 的。即使使用 HikariCP 这样的连接池,每个线程仍然要等 SQL 查询完成才能执行下一步操作,这在高并发场景下会影响吞吐量。

R2DBC 通过异步、非阻塞 访问数据库,使线程不需要等待数据库返回结果,而是可以继续执行其他任务,提升应用的吞吐量。

适用场景:

  • 需要高吞吐、低延迟 的应用
  • 微服务架构,特别是基于 WebFlux 的 Spring Boot 项目
  • 云原生应用,可以充分利用 Reactor 流式处理特性
2.2、R2DBC 关键特性

R2DBC 关键特性:

  1. 完全异步:基于 Netty 事件循环,无需线程阻塞等待数据库响应。
  2. 流式处理:支持 Flux(多个结果) 和 Mono(单个结果) 数据返回,适用于 Reactor 响应式编程。
  3. 无连接池:不像 JDBC 依赖连接池,而是基于事件驱动模型直接管理数据库连接,提高资源利用率。
  4. 支持事务:可编写响应式事务,支持 @Transactional

2.3、R2DBC 与 JDBC 的对比

特性

R2DBC

JDBC

编程模型

响应式(Reactor Flux & Mono

阻塞式(同步 JDBC 连接)

并发处理

高并发(事件驱动,无需线程等待)

受限于线程池 & 连接池

线程管理

无需线程池(减少上下文切换)

依赖线程池(HikariCP 等)

适用场景

高吞吐、非阻塞 WebFlux 应用

传统 Spring MVC 应用

事务处理

响应式事务(异步方式)

传统事务(同步方式)

2.4、R2DBC 主要组件
  • ConnectionFactory:类似 JDBC 的 DataSource,用于创建数据库连接
  • Connection:表示数据库连接,提供执行 SQL 语句的能力
  • DatabaseClient:Spring 提供的 API,类似 JdbcTemplate,但基于响应式编程
  • R2dbcTransactionManager:Spring 提供的响应式事务管理器

3、Spring R2DBC 进行数据库操作的示例

这个示例展示了如何在 Spring 下配置和使用 R2DBC,包括 数据库连接、查询、事务管理 等。

3.1、添加依赖

首先,确保你在 pom.xml 中添加了 Spring R2DBC 和数据库驱动依赖。例如,使用 PostgreSQL:

<dependencies><!-- Spring R2DBC 核心 --><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-r2dbc</artifactId><version>5.3.39</version></dependency><!-- R2DBC SPI(通用 API) --><dependency><groupId>io.r2dbc</groupId><artifactId>r2dbc-spi</artifactId><version>0.9.1.RELEASE</version></dependency><!-- R2DBC PostgreSQL 驱动 --><dependency><groupId>io.r2dbc</groupId><artifactId>r2dbc-postgresql</artifactId><version>0.9.2.RELEASE</version></dependency><!-- Spring 事务管理(非 Boot 环境下手动管理事务) --><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.3.39</version></dependency>
</dependencies>

如果使用 MySQL,可以替换 PostgreSQL 依赖:

<dependency><groupId>org.mariadb</groupId><artifactId>r2dbc-mariadb</artifactId><version>1.1.2</version>
</dependency>
3.2、配置 R2DBC 数据源

在 Spring 配置类中手动创建 ConnectionFactory 和 事务管理器。

import io.r2dbc.spi.ConnectionFactories;
import io.r2dbc.spi.ConnectionFactory;
import io.r2dbc.spi.ConnectionFactoryOptions;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.r2dbc.connection.R2dbcTransactionManager;
import org.springframework.transaction.ReactiveTransactionManager;import static io.r2dbc.spi.ConnectionFactoryOptions.*;@Configuration
public class R2dbcConfig {@Beanpublic ConnectionFactory connectionFactory() {return ConnectionFactories.get(ConnectionFactoryOptions.builder().option(DRIVER, "postgresql")  // 如果是 MySQL,这里改为 "mariadb".option(HOST, "localhost").option(PORT, 5432).option(USER, "myuser").option(PASSWORD, "mypassword").option(DATABASE, "mydb").build());}@Beanpublic ReactiveTransactionManager transactionManager(ConnectionFactory connectionFactory) {return new R2dbcTransactionManager(connectionFactory);}
}
3.3、创建数据库模型

我们使用一个简单的 User 实体类:User.java

public class User {private Long id;private String name;public User(Long id, String name) {this.id = id;this.name = name;}public Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getName() { return name; }public void setName(String name) { this.name = name; }@Overridepublic String toString() {return "User{id=" + id + ", name='" + name + "'}";}
}
3.4、创建 DatabaseClient 进行数据库操作

DatabaseClient 是 Spring 提供的 R2DBC API,用于执行 SQL 查询。

import org.springframework.r2dbc.core.DatabaseClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;public class UserRepository {private final DatabaseClient databaseClient;public UserRepository(DatabaseClient databaseClient) {this.databaseClient = databaseClient;}public Flux<User> findAllUsers() {return databaseClient.sql("SELECT * FROM users").map(row -> new User(row.get("id", Long.class), row.get("name", String.class))).all();}public Mono<Void> insertUser(String name) {return databaseClient.sql("INSERT INTO users (name) VALUES (:name)").bind("name", name).then();}
}
3.5、使用事务管理

R2dbcTransactionManager 提供了响应式事务管理,可以使用 @Transactional 或手动管理事务。

import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Mono;@Service
public class UserService {private final DatabaseClient databaseClient;public UserService(DatabaseClient databaseClient) {this.databaseClient = databaseClient;}@Transactionalpublic Mono<Void> updateUser(Long id, String newName) {return databaseClient.sql("UPDATE users SET name = :name WHERE id = :id").bind("name", newName).bind("id", id).then();}
}

如果不想用 @Transactional,也可以手动管理事务:

import org.springframework.r2dbc.connection.ConnectionFactoryUtils;
import org.springframework.transaction.ReactiveTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.reactive.TransactionalOperator;
import reactor.core.publisher.Mono;public class UserService {private final DatabaseClient databaseClient;private final TransactionalOperator transactionalOperator;public UserService(DatabaseClient databaseClient, ReactiveTransactionManager transactionManager) {this.databaseClient = databaseClient;this.transactionalOperator = TransactionalOperator.create(transactionManager);}public Mono<Void> updateUser(Long id, String newName) {return databaseClient.sql("UPDATE users SET name = :name WHERE id = :id").bind("name", newName).bind("id", id).then().as(transactionalOperator::transactional);  // 手动管理事务}
}
3.6、测试 R2DBC 代码

创建 MainApp.java 运行测试:

import io.r2dbc.spi.ConnectionFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.r2dbc.core.DatabaseClient;
import reactor.core.publisher.Mono;public class MainApp {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(R2dbcConfig.class);DatabaseClient databaseClient = DatabaseClient.create(context.getBean(ConnectionFactory.class));UserService userService = new UserService(databaseClient);// 插入数据userService.insertUser("Alice").block();// 查询数据userService.findAllUsers().doOnNext(System.out::println).blockLast();context.close();}
}

4、R2DBC 通常使用 PostgreSQL,而不是 MySQL

在 R2DBC 生态中,PostgreSQL 更受欢迎,而 MySQL 的支持相对较弱,主要原因在于 异步协议支持、驱动成熟度、事务管理及适用场景。R2DBC 依赖数据库的 原生异步通信,PostgreSQL 天生支持非阻塞查询、事务提交及 LISTEN/NOTIFY 机制,能够真正发挥响应式编程的优势;而 MySQL 主要基于 同步协议,即便在 MySQL 8.0 引入部分异步能力,仍难以达到相同效果。

此外,MySQL 的 R2DBC 驱动 主要由社区维护,如 mysql-r2dbc(MariaDB Foundation 维护),其 事务隔离级别、存储过程等特性支持有限,相比之下,PostgreSQL 由 R2DBC 官方维护,功能更完善、性能更稳定。在事务管理上,PostgreSQL 完全支持 R2dbcTransactionManager,而 MySQL 受 连接池特性 影响,可能导致事务行为异常。

在 云原生、高并发、WebFlux 这类现代架构下,PostgreSQL 由于 高效的连接管理、更强的 JSON 处理能力、原生异步通知,比 MySQL 适应性更强。因此,如果项目需要 R2DBC,建议优先选择 PostgreSQL;若 没有响应式需求,MySQL 仍可采用传统 JDBC 方案。


X、后记

Spring R2DBC 的出现,为 响应式关系型数据库访问 提供了一个现代化的解决方案,使得开发者可以 充分利用异步编程的优势,提升应用的 吞吐量和性能。但在实际应用中,我们仍需根据业务需求权衡是否采用 响应式数据库访问,毕竟 传统 JDBC 在大部分应用场景下仍然稳定高效。

在 WebFlux 驱动的 微服务架构、云原生应用、实时数据处理 等场景下,Spring R2DBC 结合 Reactor 的强大能力,使得 非阻塞数据库访问 成为可能,并带来了更好的 资源利用率和性能优化。不过,选择合适的数据库驱动(如 PostgreSQL 而非 MySQL),合理管理 响应式事务,并深入理解 响应式编程模型,才能真正发挥 R2DBC 的优势。

希望本篇文章能帮助你 掌握 Spring R2DBC 的核心技术,并在实际开发中 更高效地构建响应式数据库访问方案。如果你有任何问题或实践经验,欢迎交流探讨,共同推动 Spring 响应式生态 的发展!


http://www.ppmy.cn/server/171459.html

相关文章

第4章 4.4 EF Core数据库迁移 Add-Migration UpDate-Database

4.4.1 数据库迁移原理 总结一下就是&#xff1a; 1. 数据库迁移命令的执行&#xff0c;其实就是生成在数据库执行的脚本代码&#xff08;两个文件&#xff1a;数字_迁移名.cs 数字_迁移名.Designer.cs&#xff09;&#xff0c;用于对数据库进行定义和修饰。 2. 数据库迁移…

【文献阅读】A Survey on Model Compression for Large Language Models

大语言模型模型压缩综述 摘要 大语言模型&#xff08;LLMs&#xff09;已成功变革了自然语言处理任务。然而&#xff0c;其庞大的规模和高昂的计算需求给实际应用带来了挑战&#xff0c;尤其是在资源受限的环境中。模型压缩已成为应对这些挑战的关键研究领域。本文对大语言模…

哔哩哔哩IT私塾python爬虫视频教程中的项目文件

视频链接&#xff1a; Python课程天花板,Python入门Python爬虫Python数据分析5天项目实操/Python基础.Python教程_哔哩哔哩_bilibili 视频教程中要访问的链接&#xff1a; 豆瓣电影 Top 250 httpbin.org seo推广公司网站模板_站长素材 Examples - Apache ECharts WordCloud…

Vue框架学习

一、Vue3 基础 创建vue3工程 安装Node.js在你所要存放目录位置 cmd 终端运行 npm create vuelatest输入工程名字需要ts JSX 选No 是否配置路由 NO&#xff08;初步学习&#xff09; 是否配置管理 No 是否配置测试 No Testing Solution NO 是否选择ESLint语法检查先不选 选NO…

网络运维学习笔记(DeepSeek优化版)005网工初级(HCIA-Datacom与CCNA-EI)链路层发现协议与VLAN技术

文章目录 一、链路层发现协议1.1 思科CDP协议1.2 华为LLDP协议 二、VLAN&#xff08;Virtual Local Area Network&#xff0c;虚拟局域网&#xff09;技术详解2.1 基本概念2.2 技术特性2.3 接口工作原理2.3.1 Access模式2.3.2 Trunk模式 2.4 厂商配置对比思科配置华为配置 2.5 …

渗透第二次作业

1、seacmsv9报错注入出管理员账号密码 注入漏洞的文件路径:seacmsv9.1\upload\comment\api\index.php 注入点&#xff1a;&$rlist 经源代码分析,可用以下语句注入&#xff0c;得到用户名&#xff1a; http://127.0.0.1/seacmsv9.1/upload/comment/api/index.php?gid1&…

Logic-RL: 小模型也能强推理,通过基于规则的强化学习提升大语言模型结构化推理能力

这篇论文探讨了基于规则的强化学习&#xff08;RL&#xff09;如何解锁LLM中的高级推理能力。通过在受控的逻辑谜题上进行训练并强制执行结构化的思考过程&#xff0c;即使是相对较小的模型也能开发出可转移的问题解决策略。这种方法不仅提高了逻辑任务的性能&#xff0c;而且在…

android studio 中止了一个已建立的连接

试了重启软件或者换镜像源也没用&#xff0c;发现是gradle连下载都没开始。 排查后发现android studio软件和电脑手动开启热点后冲突&#xff0c;把电脑的热点关闭后正常。