Java —— @DS切换数据源(在同一类 / 方法中访问不同的数据库)

本文介绍如何在Java应用中实现多数据源的动态切换,包括配置动态数据源starter、使用@DS注解来指定数据源,以及集成Druid进行性能监控的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

如何在同一个java文件中自由切换,访问不同的数据源?

适用情况

不同数据库之间的数据库传输

不同数据库之间的数据核对

。。。

解决

MyBatis-Plus多数据源官方介绍

一定要看下面这个文件!

GitHub动态数据源

步骤

引入dynamic-datasource-spring-boot-starter。 

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

配置数据源。

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #设置严格模式,默认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
          schema: db/schema.sql # 配置则生效,自动初始化表结构
          data: db/data.sql # 配置则生效,自动初始化数据
          continue-on-error: true # 默认true,初始化失败是否继续
          separator: ";" # sql默认分号分隔符
          
       #......省略
       #以上会配置一个默认库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:

 

使用 @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");
  }
}

集成Druid

项目引入 druid-spring-boot-starter 依赖。 

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.1</version>
</dependency>

 

排除原生Druid的快速配置类。

@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
public class Application {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

 

某些springBoot的版本上面可能无法排除可用以下方式排除。

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

 

 

 

 

### Spring Boot数据源配置中@DS注解无法找到Primary数据源的解决方案 在Spring Boot项目中,当使用`@DS`注解实现多数据源切换时,可能会遇到找不到Primary数据源的问题。这通常是由于未正确指定默认的数据源或者未按照框架的要求完成必要的配置所致。 #### 1. 配置默认数据源 根据描述,在多数据源场景下,默认数据源的作用至关重要。如果没有显式定义默认数据源,则可能导致运行时异常。可以通过以下方式设置默认数据源: - 使用`AbstractRoutingDataSource`中的`setDefaultTargetDataSource()`方法来设定默认数据源[^1]。 ```java @Configuration public class DataSourceConfig { @Bean public DataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource) { DynamicDataSource dynamicDataSource = new DynamicDataSource(); Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put("master", masterDataSource); targetDataSources.put("slave", slaveDataSource); dynamicDataSource.setDefaultTargetDataSource(masterDataSource); // 设置默认数据源为主库 dynamicDataSource.setTargetDataSources(targetDataSources); // 添加其他数据源映射关系 return dynamicDataSource; } } ``` 上述代码片段展示了如何通过`DynamicDataSource`类(继承自`AbstractRoutingDataSource`)来配置多个目标数据源以及默认数据源[^3]。 --- #### 2. 正确标注Primary数据源 如果存在多个`@Configuration`类用于定义不同数据源实例,则需要明确标记其中一个为Primary数据源。这是为了避免Spring容器初始化过程中因歧义而抛出异常。 可以在主数据源对应的配置类上添加`@Primary`注解,确保其优先级最高: ```java @Bean @Primary public DataSource masterDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/master_db"); dataSource.setUsername("root"); dataSource.setPassword("password"); return dataSource; } @Bean public DataSource slaveDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/slave_db"); dataSource.setUsername("root"); dataSource.setPassword("password"); return dataSource; } ``` 此处利用了`@Primary`注解指定了`masterDataSource`作为主要数据源[^4]。 --- #### 3. 动态切换逻辑完善 对于动态切换数据源的需求,需依赖于线程上下文中存储的信息。例如,可通过工具类维护当前请求所使用的数据源名称,并将其传递给`determineCurrentLookupKey()`方法以供判断依据。 以下是典型实现示例: ```java // 工具类:负责保存/清除当前线程绑定的数据源类型 public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); public static void setDataSourceType(String dsType) { contextHolder.set(dsType); } public static String getDataSourceType() { return contextHolder.get(); } public static void clearDataSourceType() { contextHolder.remove(); } } // 自定义数据源路由器 public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); // 获取当前线程绑定的数据源键值 } } ``` 此部分实现了基于线程局部变量(`ThreadLocal`)的方式记录每次调用所需的具体数据源标识符。 --- #### 4. Mapper层配合@DS注解 最后一步是在MyBatis Plus集成环境下合理运用`@DS`注解标明各Mapper接口关联的目标数据库资源。例如: ```java @Mapper @DS("slave") // 明确指出该Mapper对应的是从库(slave) public interface SlaveUserMapper extends BaseMapper<User> {} ``` 注意,只有当业务逻辑中有明确需求指向特定数据源时才应采用这种方式;否则将沿用全局范围内的默认行为——即访问已声明好的Primary数据源。 --- ### 总结 综上所述,针对Spring Boot数据源配置中`@DS`注解放生“找不到Primary数据源”的问题,可以从以下几个方面入手排查并修复: 1. **确认是否存在有效且唯一被设为Primary的数据源**; 2. **验证是否正确定义了抽象路由型数据源及其内部成员属性赋值过程**; 3. **检查实际执行路径下的线程环境变量状态是否匹配预期条件**。 只要遵循以上指导原则逐一调整相应环节即可顺利解决问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇宙超级无敌程序媛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值