mybatis动态切换数据源

1、分别创建两个实体类用来储存属性值:我的属性值是利用Spring注解直接从yml文件中读取的

package cn.toroot.bj.config.dataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
 * Mr peng
 * 2020-6-11 10:04:49
 * 描述:业务库的数据源实体类
 */
@Configuration
public class BusinessDataSourceConfig {

    @Value("${datasource.url1}")
    private String url;
    @Value("${datasource.username1}")
    private String username;
    @Value("${datasource.password1}")
    private String password;
    @Value("${datasource.driverClassName}")
    private String driverClassName;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }
}


package cn.toroot.bj.config.dataSource;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
 * Mr peng
 * 2020-6-11 10:04:49
 * 描述:元数据的数据源实体类
 */
@Configuration
public class SourceDataSourceConfig {

    @Value("${datasource.url2}")
    private String url;
    @Value("${datasource.username2}")
    private String username;
    @Value("${datasource.password2}")
    private String password;
    @Value("${datasource.driverClassName}")
    private String driverClassName;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

}

2、创建数据源配置类

package cn.toroot.bj.config.dataSource;

import cn.toroot.bj.core.constant.DataSourceConstant;
import dm.jdbc.pool.DmdbDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * Mr peng
 * 2020-6-11 10:22:07
 * 数据源配置类
 */
@Configuration
public class DataSourceComponent {

    @Resource
    private BusinessDataSourceConfig businessDataSourceConfig;

    @Resource
    private SourceDataSourceConfig sourceDataSourceConfig;

    //5237
    @Bean(name = "business")
    public DataSource businessDataSource() {
        return createDataSourece(businessDataSourceConfig.getUrl(),businessDataSourceConfig.getUsername(),
                businessDataSourceConfig.getPassword(),businessDataSourceConfig.getDriverClassName());
    }
    //5252
    @Bean(name = "source")
    public DataSource sourceDataSource() {
        return createDataSourece(sourceDataSourceConfig.getUrl(),sourceDataSourceConfig.getUsername(),
                sourceDataSourceConfig.getPassword(),sourceDataSourceConfig.getDriverClassName());
    }

    @Primary //不加这个会报错。
    @DependsOn({ DataSourceConstant.BUSINESS, DataSourceConstant.SOURCE})
    @Bean(name = "multiDataSource")
    public MultiRouteDataSource exampleRouteDataSource(@Qualifier("business")DataSource business,@Qualifier("source")DataSource source) {
        MultiRouteDataSource multiDataSource = new MultiRouteDataSource();
        Map<Object, Object> targetDataSources = new HashMap<>();
        //DataSourceConstant.BUSINESS = 数据源的常量Key值
        targetDataSources.put(DataSourceConstant.BUSINESS, business);
        targetDataSources.put(DataSourceConstant.SOURCE, source);
        multiDataSource.setTargetDataSources(targetDataSources);
        //设置默认数据源
        multiDataSource.setDefaultTargetDataSource(business);
        return multiDataSource;
    }

    public DataSource createDataSourece(String url,String username,String password,String driverClassName){
        DataSourceBuilder factory = DataSourceBuilder.create()
                .type(DmdbDataSource.class)
                .driverClassName(driverClassName)
                .url(url)
                .username(username)
                .password(password);
        return factory.build();
    }
}

3、创建数据源上下文实体类

package cn.toroot.bj.config.dataSource;

/**
 * Mr peng
 * 2020-6-11 10:21:41
 * 数据源上下文
 */
public class DataSourceContext {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    //执行SQL前调用此方法设置数据源
    public static void setDataSource(String value) {
        contextHolder.set(value);
    }

    public static String getDataSource() {
        return contextHolder.get();
    }

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

4、最后继承AbstractRoutingDataSource类重写函数决定最后选择的DataSource

package cn.toroot.bj.config.dataSource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/*
 *  Mr peng
 *  2020-6-11 10:22:41
 *  重写的函数决定了最后选择的DataSource
 */
public class MultiRouteDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContext.getDataSource();
    }
}

5、用例如下,看项目需求,也可以使用AOP来进行前置管理,因项目无需要,我这里咱是没有使用AOP

    private Map<String, Map<ModeAndTable, ModeTableField>> findAllJdModeTableKey() {
    	//设置数据源
        DataSourceContext.setDataSource(DataSourceConstant.SOURCE);
        List<TGxzcXxzyJd> jdList = conllectionTemplateMapper.findAll();
        Map<String, Map<ModeAndTable, ModeTableField>> ret = new HashMap<>();
        for (TGxzcXxzyJd jd : jdList) {
            ret.put(jd.getJdId(), findOneJdModeTableKey(jd.getJdId()));
        }
        DataSourceContext.clearDataSource();
        return ret;
    }

你可能感兴趣的:(mybatis动态切换数据源)