spring动态数据源的配置

前言

动态数据源和多数据源的区别:

  • 动态数据源只有一个自定义的动态DataSource对象和一个事务管理器对象。使用时,通过同一个事务管理器对象来操作动态DataSource里的具体数据源。
  • 多数据源是有多个DataSource对象,每个DataSource对象对应一个事务管理器对象。
    使用时,根据选择的事务管理器(通过@Transactional注解上指定的value,即事务管理器bean的id),获取对应的DataSource。

代码

1.动态数据源类
public class DynamicDataSource extends AbstractRoutingDataSource {
  //在开启事务时,会调用到此方法,
    //根据方法返回值作为key,从map中获取实际数据源
    @Override
    protected Object determineCurrentLookupKey() {
        try {
            Field targetF = this.getClass().getSuperclass().getDeclaredField("targetDataSources");
            targetF.setAccessible(true);
            Map<Object, Object> targetV = (Map<Object, Object>) targetF.get(this);

            String ds = DynamicDataSourceContextHolder.getDataSourceType();

            if (ds != null)
                System.out.println("操作的数据源是: "
                        + ds + "->url:" + ((DruidDataSource) targetV.get(ds)).getUrl());
            return DynamicDataSourceContextHolder.getDataSourceType();

        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return "ds1";
    }

}
2.数据源配置类
   private ComboPooledDataSource getDs1() {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        try {
            comboPooledDataSource.setDriverClass(driverClass);
            comboPooledDataSource.setJdbcUrl(jdbcUrl);
            comboPooledDataSource.setUser(user);
            comboPooledDataSource.setPassword(password);
            comboPooledDataSource.setMinPoolSize(10);
            comboPooledDataSource.setMaxPoolSize(100);
            comboPooledDataSource.setMaxIdleTime(1800);
            comboPooledDataSource.setAcquireIncrement(3);
            comboPooledDataSource.setMaxStatements(1000);
            comboPooledDataSource.setInitialPoolSize(10);
            comboPooledDataSource.setIdleConnectionTestPeriod(60);
            comboPooledDataSource.setAcquireRetryAttempts(30);
            comboPooledDataSource.setBreakAfterAcquireFailure(false);
            comboPooledDataSource.setTestConnectionOnCheckout(false);
            comboPooledDataSource.setAcquireRetryDelay(100);
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return comboPooledDataSource;
    }

    private ComboPooledDataSource getDs2() {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        try {
            comboPooledDataSource.setDriverClass(driverClass);
            comboPooledDataSource.setJdbcUrl(jdbcUrl1);
            comboPooledDataSource.setUser(user);
            comboPooledDataSource.setPassword(password);
            comboPooledDataSource.setMinPoolSize(10);
            comboPooledDataSource.setMaxPoolSize(100);
            comboPooledDataSource.setMaxIdleTime(1800);
            comboPooledDataSource.setAcquireIncrement(3);
            comboPooledDataSource.setMaxStatements(1000);
            comboPooledDataSource.setInitialPoolSize(10);
            comboPooledDataSource.setIdleConnectionTestPeriod(60);
            comboPooledDataSource.setAcquireRetryAttempts(30);
            comboPooledDataSource.setBreakAfterAcquireFailure(false);
            comboPooledDataSource.setTestConnectionOnCheckout(false);
            comboPooledDataSource.setAcquireRetryDelay(100);
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
        return comboPooledDataSource;
    }

    @Bean
    public DataSource dynamicDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        ComboPooledDataSource ds1 = getDs1();
        targetDataSources.put("ds1", ds1);
        targetDataSources.put("ds2", getDs2());
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(ds1);

        DynamicDataSourceContextHolder.dataSourceIds.add("ds1");
        DynamicDataSourceContextHolder.dataSourceIds.add("ds2");
        return dynamicDataSource;
    }
3.切面
@Aspect
@Order(-1)
@Component
public class DynamicDataSourceAspect {
    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);
    
    @Before("@annotation(ds)")
    public void changeDataSource(JoinPoint point, TargetDataSource ds) {
        //这个就是数据源标识
        String dsId = ds.name();
        
        if (!DynamicDataSourceContextHolder.containsDataSource(dsId)) {
            logger.error("数据源【{}】不存在,使用默认数据源 > {}",
                    ds.name(),
                    point.getSignature());
        }
        else {
            logger.debug("Use dataSource : {} > {}",
                    ds.name(),
                    point.getSignature());
            //如果容器中有数据源,那么就把数据源标识设置到ThreadLocal中
            DynamicDataSourceContextHolder.setDataSourceType(dsId);
        }
    }

    @After("@annotation(ds)")
    public void releaseLocal(JoinPoint point, TargetDataSource ds) {
        logger.info("==释放ds:" + ds.name() + "的ThreadLocal绑定==");
        if(DynamicDataSourceContextHolder.getDataSourceType() != null) {
            DynamicDataSourceContextHolder.getContextHolder().remove();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值