由於最近項目公司須要,須要在mybatis上配置多數據源。多數據源在jpa中配置仍是相對簡單的,由於個個數據源對應的持久化類相對獨立。可是在mybatis上配置仍是比較麻煩的。網上找到的教程大多對於目前的項目是須要有比較大的改動的。看到關於不是用spring實現多數據源用到了aop。java
參考了這篇文章 http://blog.csdn.net/gaofuqi/article/details/46417281。可是這篇文章上缺乏一些細節。對於技術比較紮實的人來講,固然沒有什麼問題。我主要是把缺失的細節補上去。mysql
<!-- base dataSource --> <bean name="mysqlDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${db.mysql.url}" /> <property name="username" value="${db.mysql.user}" /> <property name="password" value="${db.mysql.password}" /> <!-- 配置監控統計攔截的filters --> <property name="filters" value="mergeStat,wall,log4j2" /> <property name="initialSize" value="5" /> <property name="maxActive" value="100" /> <property name="minIdle" value="10" /> <property name="maxWait" value="60000" /> <property name="validationQuery" value="SELECT 'x'" /> <property name="testOnBorrow" value="true" /> <property name="testOnReturn" value="true" /> <property name="testWhileIdle" value="true" /> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="removeAbandoned" value="true" /> <property name="removeAbandonedTimeout" value="1800" /> <property name="logAbandoned" value="true" /> </bean> <bean name="oracleDataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${db.oracle.url}" /> <property name="username" value="${db.oracle.user}" /> <property name="password" value="${db.oracle.password}" /> <!-- 配置監控統計攔截的filters --> <property name="filters" value="mergeStat,wall,log4j2" /> <property name="initialSize" value="5" /> <property name="maxActive" value="100" /> <property name="minIdle" value="10" /> <property name="maxWait" value="60000" /> <!--<property name="validationQuery" value="SELECT 1 FROM DUAL'" />--> <property name="testOnBorrow" value="true" /> <property name="testOnReturn" value="true" /> <property name="testWhileIdle" value="true" /> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="removeAbandoned" value="true" /> <property name="removeAbandonedTimeout" value="1800" /> <property name="logAbandoned" value="true" /> </bean> <!-- 編寫spring 配置文件的配置多數源映射關係 --> <bean class="com.sanjiang.weixin.xd_admin.commons.base.DynamicDataSource" id="dataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="mysqlDataSource" key="mysql"></entry> <entry value-ref="oracleDataSource" key="oracle"></entry> </map> </property> <property name="defaultTargetDataSource" ref="mysqlDataSource"> </property> </bean>
一開始我覺得這邊配置了默認的datasource,而後程序就會用默認的mysqlDataSource。後來我發現我天真了,系統起不來了,由於我在系統中是配置了事務的。spring
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); } }
定義一個能夠設置當前線程的變量的工具類,用於設置對應的數據源名稱:sql
public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); /** * @Description: 設置數據源類型 * @param dataSourceType 數據庫類型 * @return void * @throws */ public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } /** * @Description: 獲取數據源類型 * @param * @return String * @throws */ public static String getDataSourceType() { return contextHolder.get(); } /** * @Description: 清除數據源類型 * @param * @return void * @throws */ public static void clearDataSourceType() { contextHolder.remove(); } }
定義一個aop處理類在數據庫事務開啓以前切換數據庫數據庫
public class DataSourceAspect implements MethodBeforeAdvice,AfterReturningAdvice { @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { // TODO Auto-generated method stub DataSourceContextHolder.clearDataSourceType(); } @Override public void before(Method method, Object[] args, Object target) throws Throwable { if (method.isAnnotationPresent(DataSource.class)) { DataSource datasource = method.getAnnotation(DataSource.class); DataSourceContextHolder.setDataSourceType(datasource.name()); } else { DataSourceContextHolder.setDataSourceType(DataSourceConst.MYSQL); } } } @Retention(RetentionPolicy.RUNTIME) @interface DataSource { String name(); } public class DataSourceConst { public static final String MYSQL="mysql"; public static final String ORACLE="oracle"; }
<!-- 配置切面 --> <aop:config> <aop:pointcut id="transactionPointCut" expression="execution(* com.sanjiang365.weixin.xd_admin.*.service..*.*(..))" /> <aop:advisor pointcut-ref="transactionPointCut" advice-ref="transactionAdvice" order="2" /> <aop:advisor advice-ref="dataSourceExchange" pointcut-ref="transactionPointCut" order="1"/> </aop:config>
這也是我參考的文章中沒有補全的。express
使用方法的話mybatis
查詢的話,添加下面的代碼oracle
DataSourceContextHolder.setDataSourceType(DataSourceConst.ORACLE);
若是涉及到事務的話,在在Service的接口中添加註解就ok了ide
@DataSource(name = DataSourceConst.ORACLE)