• 使用反应式关系数据库连接规范R2DBC操作MySQL数据库


    1. 简介

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

    2. 环境依赖

    基于Spring Boot 2.3.1Spring 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并没有想象中的那么难,但是间接的需要了解FluxMono等抽象概念。同时目前来说如果不和Webflux框架配合也没有使用场景。就本文的MySQL而言,R2DBC驱动还是社区维护(不得不说PgSQL就做的很好)。

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

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

    个人博客:https://felord.cn

  • 相关阅读:
    [2017-7-28]Android Learning Day7
    Codeforces Round #402 (Div. 2) D. String Game
    POJ2411 铺地砖 Mondriaan's Dream
    《大型网站系统架构的演化》
    Nginx 引入线程池,提升 9 倍性能
    《淘宝消息中间件概述》2015-07-11
    主从复制源代码分析
    深入剖析Redis主从复制
    主从复制配置
    Redis启动多端口、运行多实例
  • 原文地址:https://www.cnblogs.com/felordcn/p/13185731.html
Copyright © 2020-2023  润新知