​SpringBoot多数据源实战:动态路由 vs 显式装配 vs 三方库魔法

anan2025-03-19
SpringBoot多数据源实战:动态路由 vs 显式装配 vs 三方库魔法

一、核心方案对比

方案特点与适用场景:动态路由:适合高频切换场景(如读写分离) • 显式装配:适合独立操作不同库(如主业务库+日志库) • 三方库方案:适合快速集成场景

二、动态数据源路由(AbstractRoutingDataSource)

动态路由架构|wide

核心代码

// 1. 数据源上下文
public class DataSourceContext {
    private static final ThreadLocal CONTEXT = new ThreadLocal<>();
    
    public static void set(String ds) { CONTEXT.set(ds); }
    public static String get() { return CONTEXT.get(); }
    public static void clear() { CONTEXT.remove(); }
}

// 2. 动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContext.get();
    }
}

// 3. 配置类
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
    
    @Bean
    @ConfigurationProperties("spring.datasource.master")
    DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.slave")
    DataSource slaveDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    DataSource dynamicDataSource() {
        Map targetDataSources = new HashMap<>();
        targetDataSources.put("master", masterDataSource());
        targetDataSources.put("slave", slaveDataSource());
        
        DynamicDataSource ds = new DynamicDataSource();
        ds.setTargetDataSources(targetDataSources);
        ds.setDefaultTargetDataSource(masterDataSource());
        return ds;
    }

    @Bean
    PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}

三、显式多数据源装配

显式多数据源

实现代码

@Configuration
public class MultiDataSourceConfig {

    @Primary
    @Bean("primaryDS")
    @ConfigurationProperties("spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean("secondaryDS")
    @ConfigurationProperties("spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean("primaryJdbc")
    public JdbcTemplate primaryJdbc(@Qualifier("primaryDS") DataSource ds) {
        return new JdbcTemplate(ds);
    }

    @Bean("secondaryJdbc")
    public JdbcTemplate secondaryJdbc(@Qualifier("secondaryDS") DataSource ds) {
        return new JdbcTemplate(ds);
    }
}

四、MyBatis-Plus多数据源插件

MyBatis-Plus多数据源

快速集成

  1. 添加依赖:

    com.baomidou
    dynamic-datasource-spring-boot-starter
    3.5.1
  1. 配置YAML:
spring:
  datasource:
    dynamic:
      primary: master
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/main
          username: root
          password: 123456
        slave:
          url: jdbc:mysql://192.168.1.100:3306/logs
          username: log_user
          password: log_pass
  1. 注解使用:
@Service
public class OrderService {

    @DS("master") // 默认数据源
    public void createOrder(Order order) {
        // 使用主库
    }

    @DS("slave")
    public List getLogs() {
        // 使用从库
    }
}

五、方案选型建议

维度动态路由显式装配MyBatis-Plus
切换灵活性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
配置复杂度⭐⭐⭐⭐⭐⭐
事务管理需要自定义独立管理自动支持
学习成本

避坑指南:

  1. 动态数据源需配合@Transactional(propagation = Propagation.NOT_SUPPORTED)使用
  2. 显式装配时注意事务管理器绑定
  3. MyBatis-Plus多数据源不支持嵌套事务

选择最适合业务的方案,才是架构设计的真谛! ?

评论
请先登录再发表评论!