springboot实现分库分表时动态切换数据库(源)

springboot实现分库分表时动态切换数据库

在分库分表中,当主库挂了,需要将新插入的数据插入到从库中,可以通过动态地切换数据源来实现。在Spring Boot中,可以使用AbstractRoutingDataSource实现动态数据源切换。
具体实现步骤如下:

1、继承AbstractRoutingDataSource类,重写determineCurrentLookupKey()方法,根据具体的业务规则动态切换数据源,如下所示:
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSource();
    }
}
2、定义一个数据源上下文,用于保存当前使用的数据源的名称,如下所示:
public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
	//写入数据源
    public static void setDataSource(String dataSource) {
        contextHolder.set(dataSource);
    }
	//获取数据源
    public static String getDataSource() {
        return contextHolder.get();
    }
	//移除数据源
    public static void clearDataSource() {
        contextHolder.remove();
    }
}
3、在代码中,根据具体业务规则,动态地设置当前使用的数据源的名称,如下所示:
// 在需要切换数据源的地方,设置当前使用的数据源的名称
DataSourceContextHolder.setDataSource("secondaryDataSource");

// 执行需要访问数据库的操作
...

// 操作完成后,清除当前使用的数据源的名称
DataSourceContextHolder.clearDataSource();
4、在配置文件中,定义数据源和动态数据源的配置,如下所示:
spring.datasource.primary.url=jdbc:mysql://localhost:3306/db1
spring.datasource.primary.username=root
spring.datasource.primary.password=123456
spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.secondary.url=jdbc:mysql://localhost:3306/db2
spring.datasource.secondary.username=root
spring.datasource.secondary.password=123456
spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver
5、在代码中,使用@Primary注解标记主数据源的DataSource对象,使用@Qualifier注解指定从数据源的名称,如下所示:
@Configuration
public class DataSourceConfig {
    @Primary
    @Bean(name = "primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

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

    @Bean(name = "dataSource")
    public DynamicDataSource dataSource(@Qualifier("primaryDataSource") DataSource primaryDataSource,
                                         @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("primaryDataSource", primaryDataSource);
        targetDataSources.put("secondaryDataSource", secondaryDataSource);

        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);
        dataSource.setDefaultTargetDataSource(primaryDataSource);

        return dataSource;
    }
}

以上就是在主库挂了时,动态地切换数据源的实现方法。需要注意的是,具体的切换方法。

注意:

上面的代码中需要动态设置当前需要的数据源

但是我们往往需要设置一个默认的数据源,以下是对DynamicDataSource 的改造;

public class DynamicDataSource extends AbstractRoutingDataSource {
    // 设置默认数据源
    public void setDefaultDataSource(DataSource defaultDataSource) {
        super.setDefaultTargetDataSource(defaultDataSource);
    }
    
    @Override
    protected Object determineCurrentLookupKey() {
        // 返回当前线程绑定的数据源名称,如果为空则使用默认数据源
        return StringUtils.isNotBlank(DataSourceContextHolder.getDataSource()) ?
               DataSourceContextHolder.getDataSource() : getDefaultTargetDataSource();
    }
}

这样当我调用需要的数据源执行清除方法后就切换回默认的数据源;

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值