注:本文來源於 tianzhiwuqis 《spring+myBatis 配置多數據源,切換數據源》java
一個項目裏通常狀況下只會使用到一個數據庫,但有的需求是要顯示其餘數據庫的內容,像這樣,我認爲有兩種作法spring
一、在使用另外一個數據庫的項目裏寫一些restful接口,知足移動端PC端的同時也知足其餘應用調用數據的需求;sql
二、就是在項目裏配置多數據源;數據庫
我如今就是要使用另外一個數據庫的數據,想到了以上兩種方法,爲了更加熟悉spring,我打算使用第二種方案;我在百度上查了好多關於spring配置多數據源的blog,最後綜合一些,總結一下,用最簡潔,最直觀的方法來實現這個功能.apache
首先,單數據源配置流程以下restful
一個數據庫對應一個dataSource,而後對應sqlSession,而後再在Dao層實現,配置以下mybatis
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${datasource.driver}" /> <property name="url" value="${datasource.url}" /> <property name="username" value="${datasource.username}" /> <property name="password" value="${datasource.password}" /> <property name="initialSize" value="${datasource.initialSize}"></property> <property name="maxActive" value="${datasource.maxActive}"></property> <property name="maxIdle" value="${datasource.maxIdle}"></property> <property name="minIdle" value="${datasource.minIdle}"></property> <property name="maxWait" value="${datasource.maxWait}"></property> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mapperLocations" value="classpath:com/iquant/simulated/mapping/*.xml"></property> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.iquant.simulated.dao" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
但數據源就是這樣的配置,數據庫鏈接和一些屬性的配置--->sqlSession配置--->映射文件哦欸之--->事物管理app
若是是多數據源,有下面兩種方案ide
A和B,先看看B,分別爲兩個數據源配置兩個sqlSession,而後再Dao層實現,雖然功能實現了,可是到後期若是在增長多個數據源的話,修改複雜,維護起來也至關的麻煩,也不符合開閉原則;測試
A一樣配置了兩個dataSource,而後實現一個DynamicDataSource類,使用一個sqlSession,這樣維護起來也很是的容易,我是用的就是A,配置起來至關簡單!
毋庸置疑,兩個dataSouce
<bean id="dataSourceSig" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${datasource.driver}" /> <property name="url" value="${datasource.sig.url}" /> <property name="username" value="${datasource.username}" /> <property name="password" value="${datasource.password}" /> <property name="initialSize" value="${datasource.initialSize}"></property> <property name="maxActive" value="${datasource.maxActive}"></property> <property name="maxIdle" value="${datasource.maxIdle}"></property> <property name="minIdle" value="${datasource.minIdle}"></property> <property name="maxWait" value="${datasource.maxWait}"></property> </bean> <bean id="dataSourceSim" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${datasource.driver}" /> <property name="url" value="${datasource.sim.url}" /> <property name="username" value="${datasource.username}" /> <property name="password" value="${datasource.password}" /> <property name="initialSize" value="${datasource.initialSize}"></property> <property name="maxActive" value="${datasource.maxActive}"></property> <property name="maxIdle" value="${datasource.maxIdle}"></property> <property name="minIdle" value="${datasource.minIdle}"></property> <property name="maxWait" value="${datasource.maxWait}"></property> </bean>
而後配置本身實現的com.iquant.signal.configer.DynamicDataSource類,需指定默認的數據源,如使用其餘再進行切換
<bean id="dataSource" class="com.iquant.signal.configer.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="dataSourceSig" key="dataSourceSig"></entry> <entry value-ref="dataSourceSim" key="dataSourceSim"></entry> </map> </property> <!-- 默認使用dataSourceSig的數據源 --> <property name="defaultTargetDataSource" ref="dataSourceSig"></property> </bean>
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDBType(); } }
繼承AbstractRoutingDataSource 重寫determineCurrentLookupKey方法
實現DataSourceContextHolder類
public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setDBType(String dbType) { contextHolder.set(dbType); } public static String getDBType() { return ((String) contextHolder.get()); } public static void clearDBType() { contextHolder.remove(); } }
//注意這裏在調用service前切換到dataSourceSim的數據源 // 通過測試能夠寫到serice層 DataSourceContextHolder.setDBType("dataSouceSim"); // 若要切換其餘數據源,可能要想進行cleanDBType操做 DataSourceContextHolder.cleanDBType(); // 而後再對其餘數據源進行setDBType
這樣就完成了多數據源的配置和切換功能,之後還有數據庫添加,在配置一個dataSouce3.4.5.6.等等,就好了
參考BLOG
http://blog.csdn.net/wangpeng047/article/details/8866239
http://x125858805.iteye.com/blog/2061713