1. 前言

在使用R2DBC操作MySQL数据库 一文中初步介绍了r2dbc-mysql的使用。由于借助DatabaseClient操作MySQL,过于初级和底层,不利于开发。今天就利用Spring Data R2DBC来演示Spring 数据存储抽象(Spring Data Repository)风格的R2DBC数据库操作。

请注意:目前Spring Data R2DBC虽然已经迭代了多个正式版,但是仍然处于初级阶段,还不足以运用到生产中。不过未来可期,值得研究学习。

2. Spring Data R2DBC

Spring Data R2DBC提供了基于R2DBC反应式关系数据库驱动程序的流行的Repository抽象。但是这并不是一个ORM框架,你可以把它看做一个数据库访问的抽象层或者R2DBC的客户端程序。它不提供ORM框架具有的缓存、懒加载等诸多特性,但它抽象了数据库和对象的抽象映射关系,具有轻量级、易用性的特点。

2.1 版本对应关系

胖哥总结了截至目前Spring Data R2DBC和Spring Framework的版本对应关系:

Spring Data R2DBC

Spring Framework

1.0.0.RELEASE

5.2.2.RELEASE

1.1.0.RELEASE

5.2.6.RELEASE

1.1.1.RELEASE

5.2.7.RELEASE

1.1.2.RELEASE

5.2.8.RELEASE

一定要注意版本对应关系,避免不兼容的情况。

3. 基础依赖

上次我没有引用R2DBC连接池,这次我将尝试使用它。主要依赖如下 ,这里我还集成了Spring Webflux:

org.springframework.boot

spring-boot-starter-data-r2dbc

io.r2dbc

r2dbc-pool

dev.miku

r2dbc-mysql

org.springframework.boot

spring-boot-starter-data-jdbc

org.springframework.boot

spring-boot-starter-webflux

这里我采用的是 Spring Boot 2.3.2.RELEASE。

4. 配置

上次我们采用的是JavaConfig风格的配置,只需要向Spring IoC注入一个ConnectionFactory。这一次我将尝试在application.yaml中配置R2DBC的必要参数。

spring:

r2dbc:

url: r2dbcs:mysql://127.0.0.1:3306/r2dbc

username: root

password: 123456

以上就是R2DBC的主要配置。特别注意的是spring.r2dbc.url的格式,根据数据库的不同写法是不同的,要看驱动的定义,这一点非常重要。连接池这里使用默认配置即可,不用显式定义。

5. 编写业务代码

接下来就是编写业务代码了。这里我还尝试使用DatabaseClient来执行了DDL语句创建了client_user表,感觉还不错。

@Autowired

DatabaseClient databaseClient;

@Test

void doDDL() {

List ddl = Collections.unmodifiableList(Arrays.asList("drop table if exists client_user;", "create table client_user(user_id varchar(64) not null primary key,nick_name varchar(32),phone_number varchar(16),gender tinyint default 0) charset = utf8mb4;"));

ddl.forEach(sql -> databaseClient.execute(sql)

.fetch()

.rowsUpdated()

.as(StepVerifier::create)

.expectNextCount(1)

.verifyComplete());

}

5.1 声明数据库实体

熟悉Spring Data JPA的同学应该很轻车熟路了。

/**

* the client user type

*

* @author felord.cn

*/

@Data

@Table

public class ClientUser implements Serializable {

private static final long serialVersionUID = -558043294043707772L;

@Id

private String userId;

private String nickName;

private String phoneNumber;

private Integer gender;

}

5.2 声明CRUD接口

上面实体类中的@Table注解是有说法的,当我们的操作接口继承的是ReactiveCrudRepository 或者ReactiveSortingRepository时,需要在实体类上使用@Table注解,这也是推荐的用法。

public interface ReactiveClientUserSortingRepository extends ReactiveSortingRepository {

}

当然实体类不使用@Table注解标记时,我们还可以继承R2dbcRepository接口。然后ReactiveClientUserSortingRepository将提供一些操作数据库的方法。

然后Spring Data JPA怎么写,这里也差不多怎么写,但是有些功能现在还没有得到支持,比如上面提到的分页,还有主键策略等。

类似PagingAndSortingRepository的反应式分页功能接口目前还没有实装,会在未来的版本集成进来。

5.3 实际操作

接下来我们就要通过R2DBC实际操作MySQL数据库了。按照我们传统的逻辑写了如下的新增逻辑:

ClientUser clientUser = new ClientUser();

clientUser.setGender(2);

clientUser.setNickName("r2dbc");

clientUser.setPhoneNumber("9527");

clientUser.setUserId("snowflake");

Mono save = reactiveClientUserSortingRepository.save(clientUser);

结果数据库并没有写入数据。这时因为r2dbc-mysql不能被直接使用,只能由客户端去实现并委托给客户端去操作。

这也是R2DBC的设计原则,R2DBC的目标是最小化SPI平面,目的是消除数据库之间的差异部分,并使得整个数据库完全具有反应式和背压。它主要用作客户端库使用的驱动程序SPI,而不打算直接在应用程序代码中使用。

所以这里我们可以借助于reactor-test测试库去执行一下,改写为:

reactiveClientUserSortingRepository.save(clientUser)

.log()

.as(StepVerifier::create)

.expectNextCount(1)

.verifyComplete();

但是依然不能执行成功,提示update table [client_user]. Row with Id [snowflake] does not exist ,也就是说期望执行的是新增但是实际执行的是更新,由于数据库找不到主键为snowflake的记录就报了错。这里为什么是更新呢?

这时因为实体类在进行新增时会判断主键是否填充,如果没有填充就认为是新数据,采取真正的新增操作,主键需要数据库来自动填充;如果主键存在值则认为是旧数据则调用更新操作。胖哥同Spring Data R2DBC的项目组沟通后并没有得到友好的解决方案,不过我已经找到了方法,这里先留个坑。

那么该如何新增一条数据呢?我们只能借助于@Query注解来编写一条SQL写入了:

@Modifying

@Query("insert into client_user (user_id,nick_name,phone_number,gender) values (:userId,:nickName,:phoneNumber,:gender)")

Mono addClientUser(String userId, String nickName, String phoneNumber, Integer gender);

当添加了@Modifying后,返回值可以从Mono、Mono或者Mono任意一种选择。

reactiveClientUserSortingRepository

.addClientUser("snowflake",

"r2dbc",

"132****155",

0)

.as(StepVerifier::create)

.expectNextCount(1)

.verifyComplete();

这样就证明写成功了一条数据。

5.4 搭配Webflux使用

但是实际中该如何应用呢?目前能够想到的就是结合反应式框架Spring Webflux了,就像Spring Data JPA配合Spring MVC一样。

我们编写一个Webflux接口:

@RestController

@RequestMapping("/user")

public class ReactiveClientUserController {

@Autowired

private ReactiveClientUserSortingRepository reactiveClientUserSortingRepository;

/**

* 这里为了检验默认api 就不分层了

*

* @param userId the user id

* @return the mono

*/

@GetMapping("/{userId}")

public Mono findUserById(@PathVariable String userId) {

return reactiveClientUserSortingRepository.findById(userId);

}

}

5.5 一些测试数据参考

在低并发时,Spring MVC + JDBC表现最佳,但在高并发下,WebFlux + R2DBC使用每个已处理请求的内存最少。

在高并发下,Spring MVC + JDBC的响应时间开始下降。显然,R2DBC在更高的并发性下提供了更好的响应时间。Spring WebFlux也比使用Spring MVC的类似实现更好。

6. 总结

今天对Spring Data R2DBC进一步演示,相信你能够从中学到一些东西。由于R2DBC还是比较新,还存在一些需要改进和补充的东西。目前社区非常活跃,发展十分迅速。好了今天的文章就到这里,原创不易多多关注:码农小胖哥 如果你觉得本文很有用,请点赞、转发、再看。

关注公众号:Felordcn 获取更多资讯

响应式mysql_Spring Data R2DBC响应式操作MySQL相关推荐

  1. .NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper

    .NET 使用 MySql.Data.dll 动态库操作MySql的帮助类--MySqlHelper 參考演示样例代码,例如以下所看到的: /// <summary>/// MySql 数 ...

  2. mysql as用法_Spring Data R2DBC响应式操作MySQL

    1. 前言 在使用 R2DBC 操作 MySQL 数据库 一文中初步介绍了r2dbc-mysql的使用.但是借助于DatabaseClient操作MySQL,过于初级和底层,不利于开发.今天就利用Sp ...

  3. spring jpa 流式_从响应式Spring Data存储库流式传输实时更新

    spring jpa 流式 这篇文章详细介绍了从数据库到对该数据感兴趣的任何其他组件进行流更新的幼稚实现. 更准确地说,如何更改Spring Data R2DBC存储库以向相关订阅者发出事件. 对R2 ...

  4. 从响应式Spring Data存储库流式传输实时更新

    这篇文章详细介绍了从数据库到对该数据感兴趣的任何其他组件进行流更新的幼稚实现. 更确切地说,如何更改Spring Data R2DBC存储库以向相关订阅者发出事件. 对R2DBC和Spring的一点背 ...

  5. dbc数据库 与 mysql_使用反应式关系数据库连接规范R2DBC操作MySQL数据库

    1. 简介 三月份已经介绍过R2DBC,它是一种异步的.非阻塞的关系式数据库连接规范.尽管一些NoSQL数据库供应商为其数据库提供了反应式数据库客户端,但对于大多数项目而言,迁移到NoSQL并不是一个 ...

  6. angularjs 表单校验指令_angular4.0的模板式表单、响应式表单及其错误提示

    模板式表单 NgForm.NgModel.NgModelGroup是FormModule里的内容,NgForm会自动拦截标准的表单处理事件(eg.提交),angular用ngSubmit代替标准的表单 ...

  7. html响应式布局是什么,什么是响应式网页设计?响应式布局的实现原理

    概念 响应式网页设计最初是由 Ethan Marcotte 提出的一个概念:为什么一定要为每个用户群各自打造一套设计和开发方案?Web设计应该做到根据不同设备环境自动响应及调整.当然响应式Web设计不 ...

  8. html响应式布局平移,响应式网页设计、响应式布局的实现原理

    概念 响应式网页设计最初是由 Ethan Marcotte 提出的一个概念:为什么一定要为每个用户群各自打造一套设计和开发方案?Web设计应该做到根据不同设备环境自动响应及调整.当然响应式Web设计不 ...

  9. html 响应式布局注意问题,响应式布局总结(推荐)

    响应式布局的开发基础知识 本章主要分为以下几个部分 •正确理解响应式设计 •响应式设计的步骤 •响应式设计需要注意的问题 •响应式网页布局实现原理 第一:正确理解响应式布局 响应式网页设计就是一个网站 ...

  10. 前端设计 响应式设计_如何响应式设计

    前端设计 响应式设计 This guest post about responsive design comes from Krasimir Tsonev! 这个关于响应式设计的来宾帖子来自Krasi ...

最新文章

  1. centos 非root用户(普通用户)替换yum安装软件方法
  2. 不间断电源ups标准_UPS不间断电源全套基础知识
  3. 简单的消息发送小程序
  4. C# File类的操作
  5. Flink批处理练习
  6. Python学习总结(5)——字符串
  7. Linux 如何打开pyo文件,Python的文件类型
  8. 神经网络中的单层神经网络
  9. 图像坐标球面投影_C/C++ 图像处理(7)------图像の球面投影算法
  10. SpringBoot整合Swagger2,并设置springsecurity放行和token
  11. 谈谈 WiFi STBC
  12. 塔夫斯大学计算机教授,观汗辨健康?美国塔夫茨大学发明了一种汗液传感器
  13. 深度学习之美(张玉宏)——第四章 人生苦短我用python
  14. LabVIEW辨识颜色小游戏
  15. mactex+vscode+skim打造latex编译环境
  16. html5怎么写副标题,论文指导:论文题目副标题怎么写
  17. c语言“%”(取余)运算,特别是负数时该怎么算
  18. 今日参与会议后的感悟
  19. 强强联手 法大大电子合同金蝶云·苍穹版上线
  20. 【号外】疑似阿尔法狗回归,Master打遍世界顶尖棋手没输过

热门文章

  1. 中石油acm4985: Going Dutch 还钱问题(状压dp)
  2. GloVe损失函数的理解
  3. msp430项目编程31
  4. 个人作业-2016.12.2
  5. javascript跨域、iframe跨域访问
  6. 注册表的基本操作(.Net)
  7. c#利用反射Assembly 对类和成员属性进行操作
  8. 《DB 查询分析器》使用技巧之(七)
  9. 【ubuntu操作系统入门】Ubuntu常用命令大全一
  10. 【算法学习】【图像增强】【Retinex】源码运行