10、若依多数据源

dynamic-datasource-spring-boot-starter 是一个用于快速集成多数据源的启动器,支持Jdk 1.7+和SpringBoot 1.4.x到2.x.x。特性包括数据源分组、敏感信息加密、自定义注解和动态增加移除数据源等。该框架提供了Druid等连接池的集成,以及Mybatis-Plus等组件的解决方案。使用方法包括引入依赖、配置数据源和使用@DS注解进行数据源切换。

一、简介

dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。

其支持 Jdk 1.7+, SpringBoot 1.4.x 1.5.x 2.x.x

二、特性

  • 支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。
  • 支持数据库敏感配置信息 加密 ENC()。
  • 支持每个数据库独立初始化表结构schema和数据库database。
  • 支持无数据源启动,支持懒加载数据源(需要的时候再创建连接)。
  • 支持 自定义注解 ,需继承DS(3.2.0+)。
  • 提供并简化对Druid,HikariCp,BeeCp,Dbcp2的快速集成。
  • 提供对Mybatis-Plus,Quartz,ShardingJdbc,P6sy,Jndi等组件的集成方案。
  • 提供 自定义数据源来源 方案(如全从数据库加载)。
  • 提供项目启动后 动态增加移除数据源 方案。
  • 提供Mybatis环境下的 纯读写分离 方案。
  • 提供使用 spel动态参数 解析数据源方案。内置spel,session,header,支持自定义。
  • 支持 多层数据源嵌套切换 。(ServiceA >>> ServiceB >>> ServiceC)。
  • 提供 基于seata的分布式事务方案。
  • 提供 本地多数据源事务方案。 附:不能和原生spring事务混用。

三、约定

  1. 本框架只做 切换数据源 这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何CRUD。
  2. 配置文件所有以下划线 _ 分割的数据源 首部 即为组的名称,相同组名称的数据源会放在一个组下。
  3. 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换。
  4. 默认的数据源名称为 master ,你可以通过 spring.datasource.dynamic.primary 修改。
  5. 方法上的注解优先于类上注解。
  6. DS支持继承抽象类上的DS,暂不支持继承接口上的DS。

四、使用方法

1、引入dynamic-datasource-spring-boot-starter。(maven-central v3.6.1)

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  <version>${version}</version>
</dependency>

2、配置数据源

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: ENC(xxxxx) # 内置加密,使用请查看详细文档
          username: ENC(xxxxx)
          password: ENC(xxxxx)
          driver-class-name: com.mysql.jdbc.Driver
          
       #......省略
       #以上会配置一个默认库master,一个组slave下有两个子库slave_1,slave_2
# 多主多从                      纯粹多库(记得设置primary)                   混合配置
spring:                               spring:                               spring:
  datasource:                           datasource:                           datasource:
    dynamic:                              dynamic:                              dynamic:
      datasource:                           datasource:                           datasource:
        master_1:                             mysql:                                master:
        master_2:                             oracle:                               slave_1:
        slave_1:                              sqlserver:                            slave_2:
        slave_2:                              postgresql:                           oracle_1:
        slave_3:                              h2:                                   oracle_2:

3、使用 @DS 切换数据源

@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解

注解结果
没有@DS默认数据源
@DS(“dsName”)dsName可以为组名也可以为具体某个库的名称
@Service
@DS("slave")
public class UserServiceImpl implements UserService {

  @Autowired
  private JdbcTemplate jdbcTemplate;

  public List selectAll() {
    return  jdbcTemplate.queryForList("select * from user");
  }
  
  @Override
  @DS("slave_1")
  public List selectByCondition() {
    return  jdbcTemplate.queryForList("select * from user where age >10");
  }
}

五、连接池集成

1、集成Druid

基础介绍

本组件能简单高效完成对Druid的集成并完成其他参数的多元化配置。

提示

1、各个库可以使用不同的数据库连接池,如master使用Druid监控,从库使用HikariCP。

2、如果项目同时存在Druid和HikariCP并且未配置连接池type类型,默认Druid优先于HiKariCP。

如何集成

1、项目引入druid-spring-boot-starter依赖(maven-central v1.2.)

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>${druid.version}</version>
</dependency>

2、排除原生Druid的快速配置类

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class RuoYiAuthApplication
{
    public static void main(String[] args)
    {
        SpringApplication.run(RuoYiAuthApplication.class, args);
    }
}

3、排除springboot的版本上面可能无法排除可用以下方式排除。

spring:
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure

参数配置

1、如果参数都未配置,则保持原组件默认值。

2、如果配置了全局参数,则每一个数据源都会继承对应参数。

3、每一个数据源可以单独设置参数覆盖全局参数。

spring:
  datasource:
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: 123456
    dynamic:
      druid:
        initial-size: 
        max-active: 
        min-idle: 
        max-wait:
        time-between-eviction-runs-millis: 
        time-between-log-stats-millis: 
        stat-salmax-size:
        min-evictable-idle-time-millis: 
        max-evictable-idle-time-millis: 
        test-while-idle: 
        test-on-borrow: 
        test-on-return: 
        validation-query:
        validation-query-timeout: 
        use-global-datasource-stat: 
        async-init:
        clear-filters-enable: 
        reset-stat-enable:
        not-full-timeout-retry-count: 
        max-wait-thread-count:
        fail-fast:
        phyTimeout-millis:
        keep-alive:
        pool-prepared-statements:
        init-variants:
        init-global-variants:
        use-unfair-lock:
        kil1-when-socket-read-timeout:
        connection-properties:
        max-pool-prepared-statement-per-connection-size:init-connection-sqls:
        share-prepared-statements:
        connection-errorretry-attempts:
        break-after-acquire-failure:
        filters: stat,wall # 注意这个值和druid原生不一致,默认启动了stat,wall
        wall:
            noneBaseStatementAllow:
            callAllow:
            selectAllow:
            selectIntoAllow:
            selectInto0utfileAllow:
            selectwhereAlwayTrueCheck:
            selectHavingAlwayTrueCheck:
            selectUnionCheck:
            selectminusCheck:
            selectExceptCheck:
            selectIntersectCheck:
            createTableAllow:
            dropTableAllow:
            alterTableAllow:
            renameTableAllow:
            hintAllow:
            lockTableAllow:
            startTransactionAllow:blockAllow:
            conditionAndAlwayTrueAllow:
            conditionAndAlwayFalseAllow:
            conditionDoubleConstAllow:
            conditionLikeTrueAllow:
            selectAllColumnAllow:
            deleteAllow:deletewhereAlwayTrueCheck:
            deletewhereNoneCheck:
            updateAllow:
            updatewhereAlayTrueCheck:
            updatewhereNonecheck:
            insertAllow:
            mergeAllow:
            minusAllow:
            intersectAllow:
            replaceAllow:
            setAllow:
            commitAllow:
            rollbackAllow:
            useAllow:
            multistatementAllow:
            truncateAllow:
            commentAllow:
            strictsyntaxCheck:
            constArithmeticAllow:
            limitZeroAllow:
            describeAl1ow:showAllow:
            schemaCheck:
            tableCheck:
            functionCheck:
            objectCheck:
            variantCheck:
            mustParameterized:
            doPrivilegedAllow:
            dir:
            tenantTablePattern:
            tenantColumn:
            wrapAllow:
            metadataAllow:
            conditionOpXorAllow:
            conditionOpBitwseAllow:
            caseConditionConstAllow:
            completeInsertValuesCheck:
            insertValuesChecksize:
            selectLimit:
        stat:
          merge-sq1:
          og-slow-5q1:
          slow-sql-millis:
      datasource:
          # 主库数据源
          master:
            driver-class-name: 
            url: 
            username: 
            password: 
            druid: # 以下是独立参数,每个库可以重新设置
                initial-size:
                validation-query: select 1 from dual #比如oracle就需要重新设置这个
                public-key: #(非全局参数)设置即表示启动加密,底层会自动帮你配置相关的连接参数
                ......
                #生成publickey和密码,推荐使用本项目自带的加密方法
                #java -cp druid-1.1.10.jar com.alibaba.druid.filter.config.ConfigTools youpassword

          # 从库数据源
          # slave:
            # username: 
            # password: 
            # url: 
            # driver-class-name: 

如下即可配置访问用户和密码,访问http://localhost:8080/druid/index.html查看druid监控

六、若依多数据源

1、引入ruoyi-common-datasource模块

引入相关依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>${druid.version}</version>
</dependency>

<!-- Dynamic DataSource -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>${dynamic-ds.version}</version>
</dependency>

创建注解

​ 主库数据源只有一个,从库数据源可以配置多个(目前只有一个从库数据源,且从库数据源的名称为slave)

package com.ruoyi.common.datasource.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.baomidou.dynamic.datasource.annotation.DS;

/**
 * 主库数据源
 * 
 * @author ruoyi
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@DS("master")
public @interface Master
{

}
package com.ruoyi.common.datasource.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.baomidou.dynamic.datasource.annotation.DS;

/**
 * 从库数据源
 * 
 * @author ruoyi
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@DS("slave")
public @interface Slave
{

}

2、ruoyi-system模块使用

ruoyi-system-dev.yml

# spring配置
spring: 
  redis:
    host: localhost
    port: 6379
    password: 
  datasource:
    druid:
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: 123456
    dynamic:
      druid:
        initial-size: 5
        min-idle: 5
        maxActive: 20
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 1 FROM DUAL
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxPoolPreparedStatementPerConnectionSize: 20
        filters: stat,slf4j
        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
      datasource:
          # 主库数据源
          master:
            driver-class-name: com.mysql.cj.jdbc.Driver
            url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
            username: root
            password: admin0625
          # 从库数据源
          slave:
            username: root
            password: admin0625
            url: jdbc:mysql://localhost:3306/ry-test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
            driver-class-name: com.mysql.cj.jdbc.Driver
      # seata: true    # 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭

# seata配置
seata:
  # 默认关闭,如需启用spring.datasource.dynami.seata需要同时开启
  enabled: false
  # Seata 应用编号,默认为 ${spring.application.name}
  application-id: ${spring.application.name}
  # Seata 事务组编号,用于 TC 集群名
  tx-service-group: ${spring.application.name}-group
  # 关闭自动代理
  enable-auto-data-source-proxy: false
  # 服务配置项
  service:
    # 虚拟组和分组的映射
    vgroup-mapping:
      ruoyi-system-group: default
  config:
    type: nacos
    nacos:
      serverAddr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace:
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      namespace:

# mybatis配置
mybatis:
    # 搜索指定包别名
    typeAliasesPackage: com.ruoyi.system
    # 配置mapper的扫描,找到所有的mapper.xml映射文件
    mapperLocations: classpath:mapper/**/*.xml

# swagger配置
swagger:
  title: 系统模块接口文档
  license: Powered By ruoyi
  licenseUrl: https://ruoyi.vip

修改SysConfigController

    /**
     * @Slave注解为从库数据源的注解,也可替换为@DS("slave")
     * 自动切换数据源使用@Slave注解
     * 手动切换数据源比如根据参数不同切换数据源,使用DynamicDataSourceContextHolder.push("slave");及DynamicDataSourceContextHolder.clear();方法
     */
    @GetMapping(value = "/{configId}")
    //@Slave
    public AjaxResult getInfo(@PathVariable Long configId)
    {
        SysConfig config=new SysConfig();
        config.setConfigId(configId);
        if (configId==1){
            DynamicDataSourceContextHolder.push("slave");
            config=configService.selectConfigById(configId);
            DynamicDataSourceContextHolder.clear();
            return AjaxResult.success(config);
        }
        return AjaxResult.success(configService.selectConfigById(configId));
    }
public AjaxResult getInfo(@PathVariable Long configId)
{
    SysConfig config=new SysConfig();
    config.setConfigId(configId);
    if (configId==1){
        DynamicDataSourceContextHolder.push("slave");
        config=configService.selectConfigById(configId);
        DynamicDataSourceContextHolder.clear();
        return AjaxResult.success(config);
    }
    return AjaxResult.success(configService.selectConfigById(configId));
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HAKMxX5Z-1680335578059)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值