注:本文来源于 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