JAVA 数据库连接池系列 —— Spring Boot 2.x 整合 HikariCP 多数据源

一、场景描述

  本文是单数据源配置的衍生和续篇。关于 MySQL 数据库单数据源的配置,请参考前面 JAVA 数据库连接池系列 —— Spring Boot 2.x 整合 HikariCP 多数据源 这篇文章。

  在项目的开发过程中,特别是项目未进行微服务划分的情况下。很有可能出现一个业务请求,需要多个数据库的检索结果进行多次加工后,才能满足本次业务检索需求的场景。但是整个请求都处于同一个项目中。这样,单项目多、数据源的需求就慢慢的被团队成员所需要。

  本文主要采用的是苞米豆的动态数据源,具体可以参考开源的文档进行项目集成,本文案例也是基于此文档进行测试。

二、组件介绍
  • 特性

    • 支持数据源分组 ,适用于多种场景纯粹多库读写分离一主多从混合模式

    • 支持数据库敏感配置信息 加密 ENC()

    • 支持每个数据库独立初始化表结构 schema 和数据库 database

    • 支持自定义注解 ,需继承DS(3.2.0+)

    • 提供对DruidMybatis-PlusP6syJndi的快速集成。

    • 简化DruidHikariCp 配置,提供全局参数配置。配置一次,全局通用。

    • 提供自定义数据源来源方案。

    • 提供项目启动后动态增加移除数据源方案。

    • 提供 Mybatis 环境下的纯读写分离方案。

    • 提供使用 spel动态参数解析数据源 方案。内置spelsessionheader,支持自定义。

    • 支持多层数据源嵌套切换。(ServiceA >>> ServiceB >>> ServiceC)。

    • 提供对 shirosharding-jdbc,quartz 等第三方库集成的方案,注意事项和示例。

    • 提供基于seata的分布式事务方案。 附:不支持原生 spring 事务。

    • 提供本地多数据源事务方案。 附:不支持原生 spring 事务。

  • 约定

    • 本框架只做切换数据源这件核心的事情。

    • 配置文件所有以下划线 _ 分割的数据源首部即为组的名称,相同组名称的数据源会放在一个组下。

    • 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换。

    • 默认的数据源名称为 master ,你可以通过 spring.datasource.dynamic.primary 修改。

    • 方法上的注解优先于类上注解。

三、组件引入
  • 依赖版本

    <properties>
        <!-- 2020-07-12 -->
        <mysql-connector.version>8.0.21</mysql-connector.version>
        <!-- 2020-10-10 -->
        <mybatis-plus.version>3.4.1</mybatis-plus.version>
        <!-- 2020-12-25 -->
        <mybatis-plus-datasource.version>3.3.1</mybatis-plus-datasource.version>
        <!-- 2019-11-26 -->
        <pagehelper.version>1.2.13</pagehelper.version>
    </properties>
    
  • 主要依赖

    <!-- MyBatis-plus 多数据源 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
        <version>${mybatis-plus-datasource.version}</version>
    </dependency>
    
  • 辅助依赖

    <!-- MySQL连接驱动依赖 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql-connector.version}</version>
    </dependency>
    
    <!-- MyBaits-plus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>${mybatis-plus.version}</version>
    </dependency>
    
    <!-- 分页插件 -->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <version>${pagehelper.version}</version>
    </dependency>
    
四、测试案例
  1. 前置说明

    • 本次实验采用两个数据库实例,一个位于腾讯云、一个位于本次开发环境

    • 两个数据库实例的测试数据库名称都是 exercise,数据库中的表也是 student

    • 通过不同环境的表中的数据来区分不同的环境

    • 案例中,在 MAPPER 中添加了 DS() 据源的注解,同时在 Service 中添加了 DS() 数据源的注解,主要是验证多数源是否生效,生效后验证哪个级别的生效。

  2. 引入相关依赖

    请参考步骤二中的依赖

  3. 配置多数据源

    spring:
    # ==================================== 数据源相关配置开始 =====================================
    
      # ==================================== 单数据源配置开始(如果使用单数据源,请删除 pom.xml 文件中的 dynamic-datasource-spring-boot-starter) =====================================
      # Hikari pool https://github.com/brettwooldridge/HikariCP
    #  datasource:
    #    name: SPRING-BOOT-SAMPLE-MYSQL
    #    driver-class-name: com.mysql.cj.jdbc.Driver
    #    url: jdbc:mysql://127.0.0.1:3306/exercise?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false
    #    username: ENC(XXXX)
    #    password: ENC(XXXX)
      # ==================================== 单数据源配置结束 =====================================
    
      # ==================================== 多数据源配置开始 =====================================
      datasource:
        dynamic:
          primary: TENCENT
          datasource:
            TENCENT:
              name: SPRING-BOOT-SAMPLE-MYSQL-TENCENT
              driver-class-name: com.mysql.cj.jdbc.Driver
              url: jdbc:mysql://127.0.0.1:3306/exercise?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false
              username: ENC(XXXX)
              password: ENC(XXXX
    
            RCS:
              name: SPRING-BOOT-SAMPLE-MYSQL-RCS
              driver-class-name: com.mysql.cj.jdbc.Driver
              url: jdbc:mysql://127.0.0.1:3306/exercise?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=false
              username: ENC(XXXX)
              password: ENC(XXXX)
        # ==================================== 多数据源配置结束 =====================================
    
        type: com.zaxxer.hikari.HikariDataSource
        hikari:
          # 连接池中允许的最小连接数。缺省值:10
          minimum-idle: 30
          # 连接池中允许的最大连接数。缺省值:10
          maximum-pool-size: 100
          # 自动提交
          auto-commit: true
          # 一个连接 idle 状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
          idle-timeout: 30000
          # 连接池名字
          pool-name: SampleProjectHikairCP
          # 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒
          max-lifetime: 1800000
          # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
          connection-timeout: 30000
          # 数据库连接测试语
          connection-test-query: SELECT 1
    # ==================================== 数据源相关配置结束 =====================================
    
    # ==================================== 数据库插件配置开始 =====================================
    mybatis-plus:
      # 一定要对应mapper映射xml文件的所在路径
      mapper-locations: classpath:mapping/**/*.xml
      # 对应实体类的路径
      type-aliases-package: com.rambo.springbootsample.model
      global-config:
        banner: false
    
    pagehelper:
      helper-dialect: mysql
      reasonable: true
      support-methods-arguments: true
      params: count=countSql
      return-page-info: check
    # ==================================== 数据库插件配置结束 =====================================
    
  4. 创建 DAO 层的数据库操作

    @DS("TENCENT")
    public interface StudentExtMapper extends StudentMapper {
    
        /**
         * 根据名字查询学生信息
         *
         * @author  Rambo
         * @date    2021/1/11 10:31
         * @param	name    学生姓名
         * @return  com.rambo.springbootsample.model.Student
         */
        List<Student> queryStudentByName(@Param("name") String name);
    }
    
  5. 创建 Service 的服务类

    @Service
    @DS("RCS")
    public class StudentServiceImpl implements StudentService {
    
        @Resource
        private StudentExtMapper studentExtMapper;
    
        @Override
        public DataResult<List<Student>> queryStudentByName(String name) {
            if (StringUtils.isEmpty(name)) {
                throw new BusinessException(ModuleServiceResponseCode.MODULE_2001);
            }
            List<Student> result = studentExtMapper.queryStudentByName(name);
            return DataResult.getDataResult(result);
        }
    }
    
  6. 创建 Controller 对外暴露接口

    @RestController
    @RequestMapping("/dynamic")
    @Slf4j
    @Api(tags = "动态数据源演示——控制器")
    public class DynamicDatasourceDemoController {
        @Resource
        private StudentService studentService;
    
        @GetMapping("/student")
        @ApiOperation(value = "根据姓名获取学生信息")
        public DataResult<List<Student>> student (@RequestParam(value = "name") String name) {
            return studentService.queryStudentByName(name);
        }
    }
    
  7. 验证测试结果

  • ServiceMapper 中都配置来 DS 数据源,默认执行的是最底层(Mapper) 所指定的数据源
    1

  • 去除 Mapper 中配置的 DS 数据源,则执行来 Service 中所指定的数据源
    2

  • 如果配置了多个 DS 指定数据源,则以最接近数据库操作的层为有效

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值