SpringBoot整合多数据源,切换.

本文详细介绍如何在Spring Boot项目中配置多个Oracle数据源,并实现动态数据源切换。包括配置文件设置、枚举类定义、数据源实例化、动态数据源类编写及本地线程变量的使用。

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

测试库为ORACLE数据库,其实都一样 ,参考地址: https://www.cnblogs.com/lhat/p/11970554.html 

测试源码 :  链接:https://pan.baidu.com/s/1b6UJaGi73868djLjdhWUjQ   提取码:zsq6

1.配置文件,重点在于配置三个数据库连接

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

#默认数据源
spring.datasource.default-datasource.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.default-datasource.username=ZHANG
spring.datasource.default-datasource.password=Zhenghe123
spring.datasource.default-datasource.driver-class-name=oracle.jdbc.driver.OracleDriver

#多数据源
#数据源1
spring.datasource.target-datasources.datasource1.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.target-datasources.datasource1.username=ZHANG
spring.datasource.target-datasources.datasource1.password=Zhenghe123
spring.datasource.target-datasources.datasource1.driver-class-name=oracle.jdbc.driver.OracleDriver
#数据源2
spring.datasource.target-datasources.datasource2.url=jdbc:oracle:thin:@localhost:1521:orcl
spring.datasource.target-datasources.datasource2.username=SHENG
spring.datasource.target-datasources.datasource2.password=Zhenghe123
spring.datasource.target-datasources.datasource2.driver-class-name=oracle.jdbc.driver.OracleDriver

# 初始连接数
spring.datasource.druid.initial-size=10
# 最大连接池数量
spring.datasource.druid.max-active=100
# 最小连接池数量
spring.datasource.druid.min-idle=10
# 配置获取连接等待超时的时间
spring.datasource.druid.max-wait=60000
# 打开PSCache,并且指定每个连接上PSCache的大小
spring.datasource.druid.pool-prepared-statements=true
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.druid.min-evictable-idle-time-millis=300000
#spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
#spring.datasource.druid.test-while-idle=true
#spring.datasource.druid.test-on-borrow=false
#spring.datasource.druid.test-on-return=false
        
#===mybatis 配置===
# 注意:一定要对应mapper映射xml文件的所在路径
mybatis.mapper-locations=classpath*:mapper/*.xml
# Mybatis SQL语句控制台打印
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启驼峰命名  譬如数据库create_time 自动映射pojo属性createTime
mybatis.configuration.map-underscore-to-camel-case=true

2.排除不自动扫数据源配置类

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@MapperScan("com.zhang.oracledb.mapper")
public class OracledbApplication {

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

}

3.创建枚举类,作为数据源的key

public enum  DataSourceType {

    /** 默认数据源key */
    DEFAULT_DATASOURCE,

    /** 数据源1key*/
    DATASOURCE1,

    /** 数据源2key*/
    DATASOURCE2,

}

4.核心配置,实例化所有数据源

@Configuration
public class DataSourceConfig {

    @Bean //读取默认数据源,并实例化
    @ConfigurationProperties(prefix = "spring.datasource.default-datasource")
    public DataSource defaultDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean //读取数据源1,并实例化
    @ConfigurationProperties(prefix = "spring.datasource.target-datasources.datasource1")
    public DataSource dataSource1() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean //读取数据源2,并实例化
    @ConfigurationProperties(prefix = "spring.datasource.target-datasources.datasource2")
    public DataSource dataSource2() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public DataSource dynamicDataSource(DataSource defaultDataSource, DataSource dataSource1, DataSource dataSource2) {
        // 注意:该方法的参数名称要和前面前面三个datasource对象在Spring容器中的bean名称一样
        // 或者使用 @Qualifier 指定具体的bean
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.DEFAULT_DATASOURCE.name(), defaultDataSource);
        targetDataSources.put(DataSourceType.DATASOURCE1.name(), dataSource1);
        targetDataSources.put(DataSourceType.DATASOURCE2.name(), dataSource2);
        return new DynamicDataSource(defaultDataSource, targetDataSources);
    }
}

5.新建 DynamicDataSource类继承 AbstractRoutingDataSource ,添加构造方法把所有数据源加入和重写 determineCurrentLookupKey方法

public class DynamicDataSource extends AbstractRoutingDataSource {

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }

    //获取数据源的核心方法, 通过key获取数据源
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType();
    }
}

6.核心方法详解

7.使用本地线程变量,控制数据源切换

/**
 * 本地线程类,获取切换移除数据源
 **/
public class DataSourceContextHolder {

    public static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<String>();

    public static void setDataSourceType(String dsType) {
        CONTEXT_HOLDER.set(dsType);
    }

    public static String getDataSourceType() {
        return CONTEXT_HOLDER.get();
    }

    public static void removeDataSourceType() {
        CONTEXT_HOLDER.remove();
    }
}

8.测试

    @GetMapping("/test1")
    public List<Map<String, Object>> test(String dataSourceIndex) {
        // 根据参数值的不同,切换数据源
        if ("1".equals(dataSourceIndex)) {
            //获取数据源1
            DataSourceContextHolder.setDataSourceType(DataSourceType.DATASOURCE1.name());
        } else if ("2".equals(dataSourceIndex)) {
            //获取数据源2
            DataSourceContextHolder.setDataSourceType(DataSourceType.DATASOURCE2.name());
        }
        List<Map<String, Object>> mapList = testMapper.selectList();
        // 清除线程内部变量数据源key ,此步一定不能少
        DataSourceContextHolder.removeDataSourceType();
        return null;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值