由于最近项目公司须要,须要在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)