springboot多数据源的配置和可能出现的问题

1.配置pom文件

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.12</version>
		</dependency>

2.配置yml文件

spring:
  datasource:
    primary:
      type: com.alibaba.druid.pool.DruidDataSource
      driverClassName: oracle.jdbc.OracleDriver
      url: jdbc:oracle:thin:@localhost/primary
      username: 1111
      password: 1111
      initialSize: 1
      minIdle: 3
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
    slave:
      type: com.alibaba.druid.pool.DruidDataSource
      driverClassName: oracle.jdbc.OracleDriver
      url: jdbc:oracle:thin:@localhost/slave
      username: 2222
      password: 2222
      initialSize: 1
      minIdle: 3
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000   

3.编写数据源相关配置类:

DynamicDataSource类

public class DynamicDataSource extends AbstractRoutingDataSource {
    private static DynamicDataSource instance;
    private static byte[] lock = new byte[0];
    private static Map<Object, Object> dataSourceMap = new HashMap<Object, Object>();

    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
        dataSourceMap.putAll(targetDataSources);
        super.afterPropertiesSet();
    }

    public Map<Object, Object> getDataSourceMap() {
        return dataSourceMap;
    }

    public static synchronized DynamicDataSource getInstance() {
        if (instance == null) {
            synchronized (lock) {
                if (instance == null) {
                    instance = new DynamicDataSource();
                }
            }
        }
        return instance;
    }

    @Override
    protected Object determineCurrentLookupKey() {
        String lookupKey = "default";
        if (StringUtils.isNotEmpty(DataSourceContextHolder.getDBType())) {
            lookupKey = DataSourceContextHolder.getDBType();
            DataSourceContextHolder.clearDBType();
        }
        return lookupKey;
    }
DataSourceConfig类
@Configuration
public class DataSourceConfig {

    @Value("${spring.datasource.primary.url}")
    private String dbUrl;
    @Value("${spring.datasource.primary.username}")
    private String username;
    @Value("${spring.datasource.primary.password}")
    private String password;
    @Value("${spring.datasource.primary.driverClassName}")
    private String driverClassName;
    @Value("${spring.datasource.primary.initialSize}")
    private int initialSize;
    @Value("${spring.datasource.primary.minIdle}")
    private int minIdle;
    @Value("${spring.datasource.primary.maxActive}")
    private int maxActive;

    @Value("${spring.datasource.slave.url}")
    private String dbUrlSlave;
    @Value("${spring.datasource.slave.username}")
    private String usernameSlave;
    @Value("${spring.datasource.slave.password}")
    private String passwordSlave;
    @Value("${spring.datasource.lzcom.driverClassName}")
    private String driverClassNameSlave;
    @Value("${spring.datasource.lzcom.initialSize}")
    private int initialSizeSlave;
    @Value("${spring.datasource.slave.minIdle}")
    private int minIdleSlave;
    @Value("${spring.datasource.slave.maxActive}")
    private int maxActiveSlave;

    @Bean
    public DynamicDataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = DynamicDataSource.getInstance();

        DruidDataSource defaultDataSource = new DruidDataSource();// 配置第一个数据源
        defaultDataSource.setUrl(this.dbUrl);
        defaultDataSource.setUsername(username);
        defaultDataSource.setPassword(password);
        defaultDataSource.setDriverClassName(driverClassName);
        defaultDataSource.setInitialSize(initialSize);
        defaultDataSource.setMinIdle(minIdle);
        defaultDataSource.setMaxActive(maxActive);

        DruidDataSource slaveDataSource = new DruidDataSource();// 配置第二个数据源
        LzcomDataSource.setUrl(this.dbUrlSlave);
        LzcomDataSource.setUsername(usernameSlave);
        LzcomDataSource.setPassword(passwordSlave);
        LzcomDataSource.setDriverClassName(driverClassNameSlave);
        LzcomDataSource.setInitialSize(initialSizeSlave);
        LzcomDataSource.setMinIdle(minIdleSlave);
        LzcomDataSource.setMaxActive(maxActiveSlave);

        Map<Object, Object> map = new HashMap<>();
        map.put("default", defaultDataSource);//分别将两个数据源put到map中
        map.put("slave", slaveDataSource);
        dynamicDataSource.setTargetDataSources(map);
        //此处必须设置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);

        return dynamicDataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(
            @Qualifier("dynamicDataSource") DataSource dynamicDataSource)
            throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/**/*.xml"));
        sqlSessionFactoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
        return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = "sqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(
            @Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory)
            throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = "jdbcTemplate")
    public JdbcTemplate lzcomJdbcTemplate(
            @Qualifier("dynamicDataSource") DataSource dynamicDataSource) {
        return new JdbcTemplate(dynamicDataSource);
    }

    @Bean(name = "dataSourceTransactionManager")
    public DataSourceTransactionManager testTransactionManager(
            @Qualifier("dynamicDataSource") DataSource dynamicDataSource) {
        return new DataSourceTransactionManager(dynamicDataSource);
    }
}

注意DataSourceConfig类中有个配置

如果之前是一个数据源而且在yml文件中给mybatis配置了如下图,当使用多数据源是你必须也sqlSessionFactory中上图标记的那段配置,不然这个配置不会生效。理解原因应该是之前是通过框架自动帮你把yml文件的配置信息配置到sqlSessionFactory中的,现在是自己去配置sqlSessionFactory,所以框架配置失效或是框架不会再去配置这个。

mybatis:
  configuration:
    map-underscore-to-camel-case: true

 

DataSourceContextHolder类

public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

    public static synchronized void setDBType(String dbType) {
        contextHolder.set(dbType);
    }

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

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

调用代码事例:service和dao和map的代码省略,下面代码为调用slave数据源的例子

    @Test	
    public void multipleDB() {
		DataSourceContextHolder.setDBType("slave");//必须先设置要调用的数据源,再调用service
		Test test = new Test();
		test.setCode("123123123123123111111");
		test.setName("123123123123123111111");
		testService.insertSelective(test);
	}

注意:此处经过测试是先去检查当前设置数据源的,再去调用的service,所以我目前的方式是在调用service之前调用DataSourceContextHolder.setDBType("slave");

但如果出现一个service中同时调用多个数据源,可能就会存在问题,如果更好调用的方法,还请多多指点,谢谢!

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页