007.SpringBoot集成多数据源

434 阅读3分钟

本节目标

  • 了解多数据源
  • 多数据源中如何切换数据源
  • 多数据源中实现事务回滚
  • 多数据源中集成p6spy

本节项目:在springboot + mybatis plus + 多数据源 + p6spy

多数据源简介

咱们这里说的多数据源特指:dynamic-datasource-spring-boot-starter。他是一个基于springboot的快速集成多数据源的启动器。其最主要的作用就是能方便的切换本地数据源,能在几个数据库中丝滑的切换并且支持几个本地数据源的事务。

文档地址:www.kancloud.cn/tracy5546/d…

集成多数据源

参照gitee.com/mayuanfei/S…下的springboot05项目创建springboot06项目。然后在其基础上进行修改。目标是,既能访问mysql数据库也能访问oracle数据库

1. SpringBoot三板斧之加入依赖

<!-- mysql的jdbc驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.46</version>
</dependency>
<!-- oracle的jdbc驱动 -->
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc6</artifactId>
    <version>11.2.0.4</version>
</dependency>
<!-- 多数据源 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.6.1</version>
</dependency>

2. SpringBoot三板斧之添加配置

spring:
  datasource:
    dynamic:
      # 性能分析插件(有性能损耗 不建议生产环境使用)
      p6spy: true
      # 严格模式 匹配不到数据源则报错
      strict: true
      # 设置主库.也就是默认操作的数据库
      primary: mysql
      datasource:
        # mysql数据源
        mysql:
          url: jdbc:mysql://192.168.0.1:3306/springboot-demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
          username: root
          password: 123456
        # oracel数据源1
        oracle18:
          url: jdbc:oracle:thin:@192.168.0.2:1521/test
          username: root
          password: 123456
          driver-class-name: oracle.jdbc.OracleDriver
          hikari:
            connectionTestQuery: SELECT 1 FROM DUAL
        # oracel数据源2    
        oracle183:
          url: jdbc:oracle:thin:@192.168.0.3:1521/orcl
          username: root
          password: 123456
          driver-class-name: oracle.jdbc.OracleDriver
          hikari:
            connectionTestQuery: SELECT 1 FROM DUAL
        # 全局hikariCP配置
        hikari:
          # 最大连接池数量
          maxPoolSize: 20
          # 最小空闲线程数量
          minIdle: 10
          # 配置获取连接等待超时的时间
          connectionTimeout: 30000
          # 校验超时时间
          validationTimeout: 5000
          # 空闲连接存活最大时间,默认10分钟
          idleTimeout: 600000
          # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟
          maxLifetime: 1800000
          # 连接测试query(配置检测连接是否有效)
          connectionTestQuery: SELECT 1
          # 多久检查一次连接的活性
          keepaliveTime: 30000

注意

由于多数据源集成了p6spy插件,所以这里只要打开这个开关即可p6spy: true

3. 修改Mapper层类

  • mysql库:由于设置为主库,所以这里的mapper类没有变化。

    @Mapper
    public interface SysUserMapper extends BaseMapper<SysUser> {
    ​
    }
    
  • oracle18

    bank表为oracle18数据库中的表,这里的@DS指定的就是对应的数据源

    @DS("oracle18")
    @Mapper
    public interface BankMapper extends BaseMapper<Bank> {
    ​
    }
    
  • oracle183

    mis_log表为oracle183数据库中的表,这里的@DS指定的就是对应的数据源

    @DS("oracle183")
    @Mapper
    public interface MisLogMapper extends BaseMapper<MisLog> {
    ​
    }
    

数据源查询测试

public Map<String, Object> testSelect() {
    Map<String, Object> result = MapUtil.newHashMap();
    // mysql数据源查询
    SysUser sysUser = sysUserMapper.selectById(3L);
    result.put("userId", sysUser.getUserId());
    result.put("userName", sysUser.getUserName());
    // oracel18数据源查询
    Bank bank = new LambdaQueryChainWrapper<>(this.bankMapper)
            .eq(Bank::getBankid, 777L)
            .one();
    result.put("bankName", bank.getBankname());
    // oracel183数据源查询
    MisLog misLog = this.misLogMapper.selectById("1664560539193565184");
    result.put("operateDate", misLog.getOperation());
    return result;
}

测试输出结果:

image-20230605095042216

多数据源事务回滚测试

@Override
@DSTransactional
public void testRollback() {
    //mysql 插入
    SysUser sysUser = new SysUser();
    sysUser.setUserName("老马77");
    sysUser.setNickName("老马哥77");
    this.sysUserMapper.insert(sysUser);
    System.out.println(sysUser);
    //18数据库 插入
    Bank bank = new Bank();
    bank.setBankid("777");
    bank.setBankname("测试银行777");
    this.bankMapper.insert(bank);
    //183数据库 插入
    MisLog misLog = new MisLog();
    misLog.setId(IdUtil.getSnowflakeNextIdStr());
    misLog.setOperation("测试插入777");
    this.misLogMapper.insert(misLog);
    int i = 1/0;
}

测试结果:

由于出现异常,这里可以看到mysql数据库和两个oracle数据库中的插入操作均无效

代码地址

gitee.com/mayuanfei/S…下的springboot06

记忆印记

  • 多数据源切换在service层,和数据源本身的绑定在mapper层。
  • 多数据源事务用@DSTransactional