mybatis动态切换数据源

    技术2022-07-12  91

    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; }
    Processed: 0.015, SQL: 9