springboot mybatis plus多数据源轻松搞定(下)

springboot mybatis plus多数据源轻松搞定 (上) 中我们使用了分包的方式实现了一个springboot项目中多个数据源的调用。也对指出了最大的缺点就是不能灵活自由的切换数据源。那么这一篇中,我们探讨一下动态的实现多数据源的方式。可以实现随心所欲的切换数据源。

基础的配置

public enum DataSourceType {
    emanage,ehr
}

建立一个线程和数据源之间的关联类

public class DataBaseContextHolder {
    private static final ThreadLocal contextHolder = new ThreadLocal<>();
    public static void setDataSourceType(DataSourceType type)
    {
        if(type == null)
        {
            throw new NullPointerException();
        }

        contextHolder.set(type);
    }
    public static DataSourceType getDataSourceType()
    {
        DataSourceType type = contextHolder.get();
        if(type == null)
        {
            //确定一个默认数据源
            return DataSourceType.emanage;
        }
        return type;
    }

    public static void clearDataSrouceType()
    {
        contextHolder.remove();
    }
}

代码比较简单。就是当我们设置一个Mapper是通过那个数据源去访问数据的时候,把设置的参数保存在contextHolder中,为了处理线程安全,采用ThreadLocal的方式。

定义动态数据源

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {

        return DataBaseContextHolder.getDataSourceType();
    }
}

定义多数据源

@Configuration
@MapperScan("com.emanage.ehr.mapper")
public class DataSourceConfig {

    @Autowired
    private Environment env;

    @Bean(name = "datasource1")
    @ConfigurationProperties(prefix = "spring.datasource.emanage")
    public DruidDataSource druidDataSource1()
    {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(name = "datasource2")
    @ConfigurationProperties(prefix = "spring.datasource.ehr")
    public DruidDataSource druidDataSource2()
    {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    public DynamicDataSource dynamicDataSource(@Qualifier("datasource1") DruidDataSource ds1,
                                               @Qualifier("datasource2")  DruidDataSource ds2)
    {
        Map targetDataSource = new HashMap<>();
        targetDataSource.put(DataSourceType.emanage, ds1);
        targetDataSource.put(DataSourceType.ehr, ds2);
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSource);
        dataSource.setDefaultTargetDataSource(ds1);
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {

        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        // 指定数据源
        bean.setDataSource(dynamicDataSource);
        bean.setMapperLocations(resolver.getResources("classpath*:mapper/**Mapper.xml"));

        return bean.getObject();
    }
    @Bean
    public DataSourceTransactionManager transactionManager(DynamicDataSource dynamicDataSource) {

        return new DataSourceTransactionManager(dynamicDataSource);
    }

}

在调用 mapper之前,在 service中执行以下代码,可以灵活的切换数据源。

DataBaseContextHolder.setDataSourceType(DataSourceType.emanage);
DataBaseContextHolder.setDataSourceType(DataSourceType.ehr);

优化升级

感觉在sevrice中调用这些代码太过繁琐,可以自己定义两个注解。

public @interface DataSourceEmanage{}
public @interface DataSourceEHr{}

然后建立一个aop类让在有些注解的mapper类执行之前,先执行相应的数据源切换。

@Aspect
@Component
public class DataSourceAop {
    @Before("@annotation(com.example.demo3.config.DataSourceEmanage)")
    public void setEmanageDataSource()
    {
        DataBaseContextHolder.setDataSourceType(DataSourceType.emanage);
    }

    @Before("@annotation(com.example.demo3.config.DataSourceEhr)")
    public void setEhrDataSource()
    {
        DataBaseContextHolder.setDataSourceType(DataSourceType.ehr);
    }
}

只需要在mapper对应的方法上面设置注解,就可以很灵活的实现不同的方法调用不同的数据源。

Original: https://www.cnblogs.com/bbird/p/13164553.html
Author: bbird2018
Title: springboot mybatis plus多数据源轻松搞定(下)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/578744/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球