明天的明天 永远的永远 未知的一切 我与你一起承担 ??

是非成败转头空 青山依旧在 几度夕阳红 。。。
  博客园  :: 首页  :: 管理

Dynamic DataSource 多数据源配置

Posted on 2024-05-20 10:33  且行且思  阅读(1978)  评论(0编辑  收藏  举报

一、前言

MybatisPlus多数据源配置主要解决的是多数据库连接和切换的问题。在一些大型应用中,由于数据量的增长或者业务模块的增多,可能需要访问多个数据库。这时,就需要配置多个数据源。

 

二、Springboot + MyBatis Plus 数据源配置

2.1、单数据源配置

2.1.1、引用依赖

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.1</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.28</version>
    </dependency>

 

2.1.2、application.yml 配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    

 

2.1.3、通用配置类

@Configuration
@MapperScan(basePackages = {"com.xx.**.mapper"})
public class MybatisPlusConfig {
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //新的分页插件配置方法(Mybatis Plus 3.4.0版本及其之后的版本)
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

 

2.1.4、使用方式

这里便不过多的说明具体的使用方式了,和正常的MyBatis plus 单库一样

 

2.2、多数据源配置

2.2.1、引用依赖

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.1</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.28</version>
    </dependency>
   <!-- 集成druid连接池 -->
   <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.9</version>
   </dependency>    
    <!-- 多数据源所需要使用到的依赖-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
        <version>3.1.0</version>
    </dependency>

 

2.2.2、在 application.yml
spring:
  # 配置数据源信息
  datasource:
    dynamic:
      # 设置默认的数据源或者数据源组,默认值为master
      primary: master
      # 严格匹配数据源,默认false,true未匹配到指定数据源时抛异常,false使用默认数据源
      strict: false
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root
          password: 123456
        slave_1:
          url: jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8&characterEncoding=utf-8&userSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
          username: root

    

 

2.2.3、通用配置类

@Configuration
@MapperScan(basePackages = {"com.xx.**.mapper"})
public class MybatisPlusConfig {
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        //新的分页插件配置方法(Mybatis Plus 3.4.0版本及其之后的版本)
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

 

2.2.14.2、使用slave数据源
@Service
@DS("slave")
public interface TreeServiceImpl  implements TreeService {

    @Autowired
   private TreeMapper treeMapper;
  /**
   *  使用 xml 自定义的查询方法
   * 
   * @return
   */
   @DataSource(value = DataSourceType.SLAVE)
   public List<ZTree> selectThreeTreeNode(String faultDate) {
           return treeMapper.selectThreeTreeNode();
   }

  /**
   *  使用 mybatis plus 的查询方法
   * 
   * @return
   */
   @DataSource(value = DataSourceType.SLAVE)
   public List<ZTree> list(String faultDate) {
           return deptMapper.list();
   }

}

 

2.2.14.4、 Q&A
2.2.14.4.1 @Transactional 和 @DS 注解一起使用时, @DS失效的问题

这是因为 @Transactional 开启事务后, 就不会重新拿数据源,因为@DS也得通过切面去获取数据源, 这样就导致了@DS失效.

 

要解决的话, 就在要切换数据源的方法上也打上@DS, 或者多个数据源有修改操作可以都打上事务注解并改变传播机制,(但这其实是分布式事务的范畴, 这样操作不能保证事务了, plus也提供了
@DSTransactional 来支持, 不够需要借助seata)
2.2.14.4.2 针对@Transactional与@DSTransactional做一个简单的解释。

@Transactional是spring的注解目的就是开启事务,所以在该注解被扫描到的时候就去获取DataSource,此时DynamicDataSourceContextHolder队列中无任务元素,所以获取到的dsKey就是null,之后通过DynamicRoutingDataSource方法中的determinePrimaryDataSource获取主库的DataSource。
@DSTransactional是mp中的注解,该注解下的所有@DS注解在invoke方法中向DynamicDataSourceContextHolder中压入元素,之后在获取determineDataSource的时候或获取到一个dsKey从而选择正确的DataSource。