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中同时调用多个数据源,可能就会存在问题,如果更好调用的方法,还请多多指点,谢谢!