天天看點

spring+myBatis 配置多資料源,切換資料源

一個項目裡一般情況下隻會使用到一個資料庫,但有的需求是要顯示其他資料庫的内容,像這樣,我認為有兩種做法

1、在使用另一個資料庫的項目裡寫一些restful接口,滿足移動端PC端的同時也滿足其他應用調用資料的需求;

2、就是在項目裡配置多資料源;

我現在就是要使用另一個資料庫的資料,想到了以上兩種方法,為了更加熟悉spring,我打算使用第二種方案;

我在百度上查了好多關于spring配置多資料源的blog,最後綜合一些,總結一下,用最簡潔,最直覺的方法來實作這個功能

首先,單資料源配置流程如下

一個資料庫對應一個dataSource,然後對應sqlSession,然後再在Dao層實作,配置如下

<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 class="org.mybatis.spring.mapper.MapperScannerConfigurer">

<property name="basePackage" value="com.iquant.simulated.dao" />

<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>

<bean id="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

但資料源就是這樣的配置,資料庫連接配接和一些屬性的配置--->sqlSession配置--->映射檔案哦欸之--->事物管理

如果是多資料源,有下面兩種方案

A和B,先看看B,分别為兩個資料源配置兩個sqlSession,然後再Dao層實作,雖然功能實作了,但是到後期如果在增加多個資料源的話,修改複雜,維護起來也相當的麻煩,也不符合開閉原則;

我們分别配置了兩個 dataSource,兩個sqlSessionFactory,兩個transactionManager,以及關鍵的地方在于MapperScannerConfigurer 的配置——使用sqlSessionFactoryBeanName屬性,注入不同的sqlSessionFactory的名稱,這樣的話,就為不同的資料庫對應的 mapper 接口注入了對應的 sqlSessionFactory。

需要注意的是,多個資料庫的這種配置是不支援分布式事務的,也就是同一個事務中,不能操作多個資料庫。這種配置方式的優點是很簡單,但是卻不靈活。

A同樣配置了兩個dataSource,然後實作一個DynamicDataSource類,使用一個sqlSession,這樣維護起來也非常的容易,我是用的就是A,配置起來相當簡單!

毋庸置疑,兩個dataSouce

<bean id="dataSourceSig" class="org.apache.commons.dbcp.BasicDataSource"

<property name="url" value="${datasource.sig.url}" />

<bean id="dataSourceSim" class="org.apache.commons.dbcp.BasicDataSource"

<property name="url" value="${datasource.sim.url}" />

然後配置自己實作的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>

sqlSession和事物和之前一樣,不用改動,實作DynamicDataSource類

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的資料源

DataSourceContextHolder.setDBType("dataSouceSim");

這樣就完成了多資料源的配置和切換功能,以後還有資料庫添加,在配置一個dataSouce3.4.5.6.等等,就行了

作者: lost blog

關于作者:專注伺服器端開發

本文版權歸作者有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連結 如有問題, 可郵件咨詢.