【具体步骤】
1、编写动态数据源相关代码。
(1) 编写DynamicDataSource类。
DynamicDataSource的主要作用是以Map的形式,来存储多个数据源。
因为该类继承了父类AbstractRoutingDataSource,在父类中,多数据源的实例是被存放在一个名为“targetDataSource”的Map类型的成员变量中。
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 实现动态切换数据源
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDbType();
}
}
(2) 编写DatabaseContextHolder类。
/**
* create by ××× on 2018/08/27
*/
public class DatabaseContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setDbType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
public static String getDbType() {
return contextHolder.get();
}
public static void clearDbType() {
contextHolder.remove();
}
}
2、编写切换数据源的拦截器。
import org.aspectj.lang.JoinPoint;
/**
* create by ××× on 2018/08/27
*
* 数据源动态切换拦截器
*/
public class DataSourceInterceptor {
/**
* 数据源切换常量
*/
public static final String MYSQL_DATASOURCE = "mySql";
public static final String SQLSERVER_DATASOURCE = "sqlServer";
/**
* 设置mysql数据源
*
* @param jp
*/
public void setMysqlDatasource(JoinPoint jp) {
DatabaseContextHolder.setDbType(MYSQL_DATASOURCE);
}
/**
* 设置数据源为sqlserver数据库所对应的数据源。
*
* @param jp
*/
public void setSqlserverDatasource(JoinPoint jp) {
DatabaseContextHolder.setDbType(SQLSERVER_DATASOURCE);
}
}
3、整体的Spring-mybatis.xml配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 配置mysql数据源 -->
<bean id="mySqlDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="username" value="${connection.mySql.username}"></property>
<property name="password" value="${connection.mySql.password}"></property>
<property name="url" value="${connection.mySql.url}"></property>
<property name="driverClassName" value="${connection.driverClassName}"></property>
<property name="maxActive" value="${connection.maxActive}"></property>
<property name="minIdle" value="${connection.minIdle}"></property>
<property name="filters" value="${connection.filters}"/>
<property name="initialSize" value="${connection.initialSize}"/>
<property name="timeBetweenEvictionRunsMillis" value="${connection.timeBetweenEvictionRunsMillis}"/>
<property name="minEvictableIdleTimeMillis" value="${connection.minEvictableIdleTimeMillis}"/>
<property name="maxOpenPreparedStatements" value="${connection.maxOpenPreparedStatements}"/>
<property name="removeAbandoned" value="${connection.removeAbandoned}"/>
<property name="removeAbandonedTimeout" value="${connection.removeAbandonedTimeout}"/>
<property name="logAbandoned" value="${connection.logAbandoned}"/>
</bean>
<!-- 配置sqlServer数据源 -->
<bean id="sqlServerDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="${connection.sqlServer.driver}"/>
<property name="url" value="${connection.sqlServer.url}"/>
<property name="username" value="${connection.sqlServer.username}"/>
<property name="password" value="${connection.sqlServer.password}"/>
</bean>
<!-- aop拦截处理,去掉也能运行对应的 dataSource -->
<bean id="dataSource" class="qgs.serviceOperation.dataSourceSwitch.DynamicDataSource">
<property name="defaultTargetDataSource" ref="mySqlDataSource"/> <!--默认主库-->
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="mySql" value-ref="mySqlDataSource"/> <!--辅助aop完成自动数据库切换-->
<entry key="sqlServer" value-ref="sqlServerDataSource"/>
</map>
</property>
</bean>
<!-- 配置切换数据源Key的拦截器 -->
<bean id="dataSourceInterceptor" class="qgs.serviceOperation.dataSourceSwitch.DataSourceInterceptor"/>
<!-- myBatis文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations">
<list>
<value>classpath:/mapper/mySql/**/*.xml</value>
<value>classpath:/mapper/sqlServer/*.xml</value>
</list>
</property>
<property name="configLocation">
<value>classpath:spring/mybatis-setting.xml</value>
</property>
</bean>
<!-- mybatis.spring自动映射 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="qgs.serviceOperation.**.dao,qgs.serviceOperation.sqlServer.customInfo.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:aspectj-autoproxy expose-proxy="true"/>
<!-- 注解方式配置事物 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Spring声明式事务切面 -->
<tx:advice id="userTxAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="delete*" propagation="REQUIRED" read-only="false"
rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException"/>
<tx:method name="insert*" propagation="REQUIRED" read-only="false"
rollback-for="java.lang.Exception"/>
<tx:method name="update*" propagation="REQUIRED" read-only="false"
rollback-for="java.lang.Exception"/>
<tx:method name="find*" propagation="SUPPORTS"/>
<tx:method name="get*" propagation="SUPPORTS"/>
<tx:method name="select*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- Spring框架自身提供的切面 -->
<aop:advisor advice-ref="userTxAdvice" pointcut="execution(public * qgs.serviceOperation.*.service..*.*(..))"
order="2"/>
<!-- 用户自定义的切面,根据切入点,动态切换数据源。 -->
<aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor" order="1">
<aop:before method="setMysqlDatasource" pointcut="execution(* qgs.serviceOperation.*.service..*.*(..))"/>
<aop:before method="setSqlserverDatasource"
pointcut="execution(* qgs.serviceOperation.sqlServer.customInfo.service..*.*(..))"/>
</aop:aspect>
</aop:config>
</beans>