由于项目需求,做了一个给予spring的动态数据源切换的工具类,数据源使用的是阿里的druid
import java.sql.SQLFeatureNotSupportedException;
import java.util.Map;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.log4j.Logger;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import com.xyh.util.SpringUtils;
/**
* @author yuanhao
* @describe 实现动态数据源切换逻辑
*/
public class DataSourceUtil extends AbstractRoutingDataSource {
private Logger log = Logger.getLogger(this.getClass());
/**
* 数据源资源池
*/
private Map<Object, Object> _targetDataSources;
/**
* 数据源名称
*/
/**
* @see org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource#determineCurrentLookupKey()
* @describe 数据源为空或者为0时,自动切换至默认数据源
*/
@Override
protected Object determineCurrentLookupKey() {
String dataSourceName = DBContextHolder.getDataSource();
try {
if (dataSourceName == null || "".equals(dataSourceName)) {// 如果传入数据源id为空
throw new Exception("传入的数据源名称为空,无法选择数据源");
}
this.selectDataSource(dataSourceName);
} catch (Exception e) {
e.printStackTrace();
}
log.debug("--------> use datasource " + dataSourceName);
return dataSourceName;
}
/**
* @param key
* 数据源id
* @throws Exception
* @describe 数据源存在连接池中时不做处理, 不存在将新数据链接添加至连接池
* /
public void selectDataSource(String dataSourceName) throws Exception {
Object obj = this._targetDataSources.get(dataSourceName);
// 如果数据源已经有了
if (obj != null) {
return;
} else {// 如果没有则从spring容器中获取
DruidDataSource dataSource = (DruidDataSource) SpringUtils
.getBeanInstance(dataSourceName);
if (dataSource != null)
this.setDataSource(dataSourceName, dataSource);
else {
throw new Exception("无法取得数据库连接配置,请核对是否已经配置");
}
}
}
/**
* 将数据源写入池中
* @param key
* @param dataSource
*/
private void setDataSource(String dataSourceName, DruidDataSource dataSource) {
//this.addTargetDataSource(dataSourceName, dataSource);
this._targetDataSources.put(dataSourceName, dataSource);
this.setTargetDataSources(this._targetDataSources);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void setTargetDataSources(Map targetDataSources) {
this._targetDataSources = targetDataSources;
super.setTargetDataSources(this._targetDataSources);
afterPropertiesSet();
}
/*
public void addTargetDataSource(String key, DruidDataSource dataSource) {
}*/
/**
* @return
* @throws SQLFeatureNotSupportedException
*/
public java.util.logging.Logger getParentLogger()
throws SQLFeatureNotSupportedException {
// TODO Auto-generated method stub
return null;
}
}
数据源选择工具类
public class DBContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
/**
* 传入数据源名称
*
* @param key
*/
public static void setDataSource(String key) {
contextHolder.set(key);
}
/**
* 取数据源名称
*
* @return
*/
public static String getDataSource() {
return contextHolder.get();
}
/**
* 销毁数据源名称
*
* @return
*/
public static void clearDataSource() {
contextHolder.remove();
}
}
spring 配置:
<!--db1-->
<bean id="dataSource411602" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close" lazy-init="true">
<property name="driverClassName">
<value>${jdbc.oracle.driverClassName}</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@192.168.0.1:20003:orcl</value>
</property>
<property name="username">
<value>test</value>
</property>
<property name="password">
<value>test</value>
</property>
<property name="filters" value="stat"></property>
</bean>
<!--db2-->
<bean id="dataSource411606" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close" lazy-init="true">
<property name="driverClassName">
<value>${jdbc.oracle.driverClassName}</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@192.168.0.2:60021:orcl</value>
</property>
<property name="username">
<value>test</value>
</property>
<property name="password">
<value>test</value>
</property>
<property name="filters" value="stat"></property>
</bean>
<!--数据源-->
<bean id="dataSource" class="com.xyh.util.dbutil.DataSourceUtil">
<property name="targetDataSources">
<map key-type="java.lang.String">
</map>
</property>
</bean>
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocations">
<list>
<value>classpath:sql-map-config.xml</value>
</list>
</property>
<property name="dataSource" ref="dataSource" />
</bean>
<!-- JDBC 事务管理 -->
<bean id="jdbcTxManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
使用的时候只需要在要切换数据源的地方写下以下代码DBContextHolder.setDataSource(beanId);
数据源就自动切换成你想要使用的那个了