有些情景需要在同一个方法或者一个流程内使用多个数据源,这时候需要将 mybatis/hibernate 来回切换数据源,本文提供一个可行的数据快速切换的方式
数据切换工具DataSourceSwitch.java
public class DataSourceSwitch {
@SuppressWarnings("rawtypes")
private static final ThreadLocal contextHolder=new ThreadLocal();
@SuppressWarnings("unchecked")
public static void setDataSourceType(String dataSourceType){
contextHolder.set(dataSourceType);
}
public static String getDataSourceType(){
return (String) contextHolder.get();
}
public static void clearDataSourceType(){
contextHolder.remove();
}
}
数据源DataSources.java
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 配置于applicationContext 中,线程局部变量ThreadLocal contextHolder 保存当前需要的数据源类型,当
* DataSourceSwitch. setDataSourceType(DataSourceInstances.XXX)
* 保存当前需要的数据源类型的时候,DataSources 会从当前线程中查找线程变量的数据源类型,从而决定使用何种数据源
*/
public class DataSources extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitch.getDataSourceType();
}
}
在spring.xml中定义数据源
<bean id="defaultDataSource" ...>...</bean>
<bean id="dataSource1" ...>...</bean>
<bean id="dataSource2" ...>...</bean>
<bean id="dataSource3" ...>...</bean>
<bean id="dataSource4" ...>...</bean>
<!-- 多数据源切换 -->
<bean id="dataSource" class="com.pengwu.common.base.util.DataSources">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="defaultDataSource" key="DEFAULT"></entry>
<entry value-ref="dataSource1" key="DATASOURCE1"></entry>
<entry value-ref="dataSource2" key="DATASOURCE2"></entry>
<entry value-ref="dataSource3" key="DATASOURCE3"></entry>
<entry value-ref="dataSource4" key="DATASOURCE4"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="defaultDataSource"></property>
</bean>
<!-- 集成到mybatis 集成hibernate类似-->
<bean id="sqlSessionFactoryDefault" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:mybatis-config.xml</value>
</property>
<property name="mapperLocations">
<list>
<value>classpath*:com/project/**/bean/*.xml</value>
</list>
</property>
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
<constructor-arg index="0" ref="sqlSessionFactoryDefault" />
</bean>
<!-- spring事物控制 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
在常量类中定义dataSource的key
public class Constants {
/**
* 多数据源
*/
public static class DATASOURCE{
/**
* 默认配置数据源
*/
public static final String DEFAULT = "DEFAULT";
public static final String DATASOURCE1 = "DATASOURCE1";
public static final String DATASOURCE2 = "DATASOURCE2";
public static final String DATASOURCE3 = "DATASOURCE3";
public static final String DATASOURCE4 = "DATASOURCE4";
}
}
使用
使用方法中切换后整个线程中mybatis将会使用该数据源,也可在同一线程中切换多次
//切换数据源指定数据源1
DataSourceSwitch.setDataSourceType(Constants.DATASOURCE.DATASOURCE1);
doSomething();
//切换数据源指定数据源2
DataSourceSwitch.setDataSourceType(Constants.DATASOURCE.DATASOURCE2);
doSomething();
//清空数据源(切换至默认数据源)
DataSourceSwitch.clearDataSourceType();
doSomething();