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

在现代应用架构中,高并发、低延迟的需求推动了 响应式编程 的发展,而传统的 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 的对比
特性R2DBCJDBC
编程模型响应式(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.rhkb.cn/news/16610.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LabVIEW商业软件开发

在商业软件开发和仪器自动测试领域&#xff0c;LabVIEW以其图形化编程方式、高效的数据采集能力和强大的硬件集成优势&#xff0c;成为众多工程项目的核心开发工具。然而&#xff0c;商业软件的开发远不止编写代码和实现功能那么简单&#xff0c;尤其是在仪器自动测试领域&…

优化关键词还有哪些软件可用?

随着2025年互联网的发展&#xff0c;越来越多的企业认识到关键词优化的重要性。SEO&#xff08;搜索引擎优化&#xff09;作为提升网站流量和排名的重要手段&#xff0c;已经成为每个企业营销战略中的核心组成部分。而在SEO优化过程中&#xff0c;关键词的选择和优化无疑是至关…

程序诗篇里的灵动笔触:指针绘就数据的梦幻蓝图<9>

大家好啊&#xff0c;我是小象٩(๑ω๑)۶ 我的博客&#xff1a;Xiao Xiangζั͡ޓއއ 很高兴见到大家&#xff0c;希望能够和大家一起交流学习&#xff0c;共同进步。 这一节是对之前内容的修整 目录 一、传值调用和传址调用二、数组名的理解三、指针访问数组四、结尾 一…

新一代SCADA: 宏集Panorama Suite 2025 正式发布,提供更灵活、符合人体工学且安全的应用体验

宏集科技宣布正式推出全新Panorama Suite 2025 SCADA软件&#xff01;全新版本标志着 Panorama Suite的一个重要里程碑&#xff0c;代表了从 Panorama Suite 2022 开始并跨越三个版本&#xff08;2022、2023、2025&#xff09;的开发过程的顶峰。 此次重大发布集中在六个核心主…

多机器人系统的大语言模型:综述

25年2月来自 Drexel 大学的论文“Large Language Models for Multi-Robot Systems: A Survey”。 大语言模型 (LLM) 的快速发展为多机器人系统 (MRS) 开辟新的可能性&#xff0c;从而增强通信、任务规划和人机交互。与传统的单机器人和多智体系统不同&#xff0c;MRS 带来独特…

【欧洲数据集】高分辨率网格气象数据集E-OBS

目录 数据概述最新版本 E-OBS 30.0e数据下载下载链接1:ECA&D官网下载链接2:ECMWF参考E-OBS 数据集(E-OBS, European high-resolution gridded dataset)是基于 European Climate Assessment & Dataset (ECA&D) 信息的高分辨率网格化观测数据集,涵盖欧洲地区的多…

游戏引擎学习第100天

仓库:https://gitee.com/mrxiao_com/2d_game_2 昨天的回顾 今天的工作重点是继续进行反射计算的实现。昨天&#xff0c;我们开始了反射和环境贴图的工作&#xff0c;成功地根据法线显示了反射效果。然而&#xff0c;我们还没有实现反射向量的计算&#xff0c;导致反射交点的代…

Mac上搭建宝塔环境并部署PHP项目

安装Docker Desktop》搭建Centos版本的宝塔环境》部署PHP项目 1. 下载Docker for mac 软件&#xff1a;https://www.docker.com/ 或使用终端命令&#xff1a;brew install --cask --appdir/Applications docker 2. 使用命令安装宝塔环境的centos7系统&#xff1a; docker pul…

从肠道菌群到炎症因子:读懂疾病的预警信号

当我们的皮肤被轻微割伤或烧伤时&#xff0c;伤口周围区域可能会变得红肿、发热&#xff0c;甚至伴有疼痛&#xff1b;感冒时&#xff0c;喉咙痛、肿胀&#xff1b;不小心扭伤后&#xff0c;可能会肿胀、疼痛和僵硬…这些都与炎症相关。 炎症&#xff0c;作为身体对损伤或感染的…

83.在 Vue3 中使用 OpenLayers 利用 TLE 计算并显示单个卫星的轨迹

1. 前言 在可视化开发中&#xff0c;卫星轨迹的实时计算与展示是一个比较有趣的应用场景。TLE&#xff08;Two-Line Element Set&#xff09;是一种用于描述卫星轨道参数的格式&#xff0c;我们可以通过 satellite.js 解析 TLE 数据&#xff0c;并计算卫星在任意时间点的位置。…

Vue3(2)

一.Vue新特性 &#xff08;1&#xff09;defineOptions:主要是用来定义Options API的选项 背景说明&#xff1a;有< script setup >之前&#xff0c;如果定义props&#xff0c;emits可以轻而易举地添加一个与setup平级 的属性。但是用了< script setup >后&#…

π 的奥秘:如何用有理数逼近无理数?

本文将围绕有理数、无理数、连续统以及它们之间的深刻联系展开讨论&#xff0c;并结合具体的数学理论如康托尔区间套定理、戴德金分割、柯西施瓦茨不等式等&#xff0c;进行简要探讨 由于本文并未深入探讨&#xff0c;可能存在部分不严谨的地方&#xff0c;也欢迎各位进行纠正…

图书管理项目(spring boot + Vue)

想要该项目的话&#xff0c;就 jia 我&#xff0c;并在评论区给我说一下&#xff0c;只需要1元&#xff0c;我把整个项目发给你 jia微&#xff1a;18439421203&#xff08;名字叫&#xff1a;Bingo&#xff09; 运行图片&#xff1a;

131,【2】 攻防世界 catcat-new

进入靶场 &#x1f431; 点击图片时发现url处很可疑 想到文件读取 ../app.py # 导入 os 模块&#xff0c;用于与操作系统进行交互&#xff0c;例如文件操作、路径操作等 import os # 导入 uuid 模块&#xff0c;用于生成通用唯一识别码&#xff0c;常用于生成随机的密钥 imp…

NO.12十六届蓝桥杯备战|关系操作符|操作符连用|浮点数比较|练习2道(C++)

关系操作符 关系操作符介绍 ⽤于⽐较的表达式&#xff0c;称为“关系表达式”&#xff08;relational expression&#xff09;&#xff0c;⾥⾯使⽤的运算符就称为“关 系运算符”&#xff08;relational operator&#xff09;&#xff0c;主要有下⾯6个。 运算符描述>⼤…

.NET Web-静态文件访问目录浏览

一、Web根目录访问 创建wwwroot文件夹app.UseStaticFiles(); // 启⽤静态⽂件中间件url/路径 进行访问 二、Web根目录之外的文件 app.UseStaticFiles(new StaticFileOptions {FileProvider new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath,&qu…

【漏洞复现】Casbin get-users 账号密码泄漏漏洞

免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删除。…

PPDock:复旦大学团队研发的蛋白质-配体“盲对接“技术

PPDock: Pocket Prediction-Based Protein−Ligand Blind Docking 发表于Journal of Chemical Information and Modeling&#xff0c;第一作者为 Jie Du&#xff0c;通讯作者为 Manning Wang&#xff0c;研究团队来自复旦大学。该研究提出一种新的基于口袋预测的蛋白质 - 配体盲…

中间件-安装Minio-集成使用(ubantu-docker)

目录 1、安装docer 2、运行以下命令拉取MinIO的Docker镜像 3、检查当前所有Docker下载的镜像 4、创建目录 5、创建Minio容器并运行 6、SDK操作 FileUploader.java 1、安装docer 参考这篇&#xff1a;Linux安装Docker 2、运行以下命令拉取MinIO的Docker镜像 docker pull…

使用 Notepad++ 编辑显示 MarkDown

Notepad 是一款免费的开源文本编辑器&#xff0c;专为 Windows 用户设计。它是替代记事本&#xff08;Notepad&#xff09;的最佳选择之一&#xff0c;因为它功能强大且轻量级。Notepad 支持多种编程语言和文件格式&#xff0c;并可以通过插件扩展其功能。 Notepad 是一款功能…