近日因为项目需求,需要动态切换数据源,就稍稍做了下研究,理解的不深,有不对的地方还望高人指点。
直接贴上代码:
resource.xml
<bean id="sqlSessionFactory" class="com.hotent.core.mybatis.SqlSessionFactoryFactoryBean">
<property name="configLocation" value="classpath:/conf/configuration.xml"/>
<property name="mapperLocations" >
<list>
<value>classpath:/com/hotent/*/maper/*.map.xml</value>
</list>
</property>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="com.hotent.core.db.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="dataSourceOrg" value-ref="dataSourceOrg" />
<entry key="defaultDataSource" value-ref="defaultDataSource" />
</map>
</property>
<property name="defaultTargetDataSource" ref="defaultDataSource" />
</bean>
<bean id="dataSourceOrg" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close" >
<property name="driverClassName" value="${jdbc.driverClassNameOrg}"/>
<property name="url" value="${jdbc.urlOrg}"/>
<property name="username" value="${jdbc.usernameOrg}"/>
<property name="password" value="${jdbc.passwordOrg}"/>
</bean>
<bean id="defaultDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close" >
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<pre name="code" class="plain">
我这里配置数据库连接池用的是 com.alibaba.druid.pool.DruidDataSource 。下面的DynamicDataSource是实现AbstractRoutingDataSource 的 。
public class DynamicDataSource extends AbstractRoutingDataSource {
/**
* 取得当前使用那个数据源。
*/
@Override
protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
// TODO Auto-generated method stub
return null;
}
//设置数据源集合.
@Override
public void setTargetDataSources(Map targetDataSources) {
super.setTargetDataSources(targetDataSources);
}
}
DbContextHolder.java
public class DbContextHolder
{
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static final String DATA_SOURCE_DEFAULT = "defaultDataSource";
public static final String DATA_SOURCE_ORG = "dataSourceOrg";
/**
* 设置当前数据库。
* @param dbType
*/
/* @Resource
private DynamicDataSource dds;*/
public static void setDbType(String dbType)
{
contextHolder.set(dbType);
}
/**
* 取得当前数据源。
* @return
*/
public static String getDbType()
{
String str = (String) contextHolder.get();
if (null == str || "".equals(str))
str = "1";
return str;
}
/**
* 清除上下文数据
*/
public static void clearDbType()
{
contextHolder.remove();
}
}
这里两个常量就是两个数据源的id.以后增加数据源,这里也要增加。setDbType就用做后面切换数据时候设置当前数据源。当完成操作以后要调用clearDbType方法恢复默认数据源。
test.java
public class test {
@Test
public void test() {
ApplicationContext cxt = new ClassPathXmlApplicationContext(new String[] {"conf/app-context.xml"});
IAuthenticate service = (IAuthenticate)cxt.getBean("iAuthenticate");
SysOrg org = new SysOrg();
org.setOrgId(123456789L);
org.setOrgName("测试数据源");
org.setAreaid(1L);
//service.add(org);
List<ISysOrg> sysorg_ =service.getAllOrgs();
JSONArray json =JSONArray.fromObject(sysorg_);
System.out.println(json.toString());
DbContextHolder.setDbType(DbContextHolder.DATA_SOURCE_ORG);//切换数据源
List<ISysOrg> sysorg_1 =service.getAllOrgs();
JSONArray json1 =JSONArray.fromObject(sysorg_1);
System.out.println(json1.toString());
DbContextHolder.clearDbType();//恢复默认数据源
}
}
运行,切换成功。
中间遇到过一个问题,一直没有解决,还不知道是为什么,我用org.logicalcobwebs.proxool.ProxoolDataSource配置数据库连接池的时候数据源无法切换,后来改成com.alibaba.druid.pool.DruidDataSource、com.hotent.core.db.DynamicDataSource都可以。暂时还没查到原因。还望高人指点一下。