这两天因为项目扩展,需要用多个数据库来存储不同的数据,为此需要改造为多数据源支持才行,特此记录下
项目的一部分是用spring boot加eureka搭建的,以下以spring boot来说明多数据源配置情况。
1、添加多数据源配置信息
在properties中添加多个不同数据源的配置
spring.datasource.pb.driverClassName = @spring.datasource.pb.driverClassName@
spring.datasource.pb.url=@spring.datasource.pb.url@
spring.datasource.pb.username=@spring.datasource.pb.username@
spring.datasource.pb.password=@spring.datasource.pb.password@
spring.datasource.ct.driverClassName = @spring.datasource.ct.driverClassName@
spring.datasource.ct.url=@spring.datasource.ct.url@
spring.datasource.ct.username=@spring.datasource.ct.username@
spring.datasource.ct.password=@spring.datasource.ct.password@
2、创建数据源类型的常量类
public class DataSourceDialect {
public static final String ORACLE_PB = "oracle-pb";
public static final String ORACLE_CT = "oracle-ct";
}
3、创建DataSourceConfig配置类,添加配置的多个数据源
@Bean(name = "pbDataSource")
@ConfigurationProperties(prefix = "spring.datasource.pb")
public DataSource pbDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "ctDataSource")
@ConfigurationProperties(prefix = "spring.datasource.ct")
public DataSource ctDataSource() {
return DataSourceBuilder.create().build();
}
注:要spring读取自定义配置的数据源,需要先禁止掉spring的自动读取数据源配置类,即在spring boot的项目启动类中加入“@SpringBootApplication(exclude = )”即可
4、重写SpringBoot的数据源配置
@Primary
@Bean("dataSource")
public DynamicDataSource dataSource(@Qualifier("pbDataSource") DataSource pbDataSource,
@Qualifier("ctDataSource") DataSource ctDataSource) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceDialect.ORACLE_PB, pbDataSource);
targetDataSources.put(DataSourceDialect.ORACLE_CT, ctDataSource);
dynamicDataSource.setTargetDataSources(targetDataSources);
// 设置默认的数据源
dynamicDataSource.setDefaultTargetDataSource(ctDataSource);
return dynamicDataSource;
}
5、根据动态数据源配置,创建sqlSessionFactory
@Primary
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("pbDataSource") DataSource pbDataSource,
@Qualifier("ctDataSource") DataSource ctDataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(this.dataSource(pbDataSource, ctDataSource));
// sessionFactory.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage"));
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
return sessionFactory.getObject();
}
6、根据动态数据源配置,创建transactionManager
public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DynamicDataSource dataSource)
throws Exception {
return new DataSourceTransactionManager(dataSource);
}
到此动态数据源配置已经完成,那么怎么自由切换为想要的数据源呢。
1、首先定义类DynamicDataSource,它继承了AbstractRoutingDataSource,里面提供了determineCurrentLookupKey方法,该方法可以获取需要使用的datasource的key
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
}
}
2、那么怎么利用该方法呢,再定义一个数据源的切换类DataSourceSwitch
public class DataSourceSwitch {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
//设置当前使用的数据源
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
//获取当前使用的数据源
public static String getDataSourceType() {
System.out.println("使用的数据源:"+contextHolder.get());
return (String) contextHolder.get();
}
// 清除当前数据源
public static void clearDataSourceType() {
contextHolder.remove();
}
}
这里利用了ThreadLocal线程来设置key值,这么做的好处在于能够保护变量被修改,比如同时有两个数据库请求进来,如果用静态变量处理的话,很容易导致第一个线程设置的key被第二个线程给修改了
3、修改DynamicDataSource类的方法
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitch.getDataSourceType();
}
到此多数据源的自由配置即完成了,通过类DataSourceSwitch提供的方法就可以自由切换为想要的数据源,配合aop切面方法还可以更灵活自由的自动搭配
- 本文链接: https://www.acgclub.xyz/archives/1561271339932
- 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!