欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。
欢迎跳转到本文的原文链接:https://honeypps.com/java/spring-mybatis-multi-datasource-props-4/
有时候需要在程序中动态切换数据源,那么这个系列的之前的博文所阐述的方法就不再使用了,总不能通过程序更改config.properties文件的dataSource的值,然后再重启web服务器以便加载applicationContext.xml文件。这里讲诉的是如何利用AbstractRoutingDataSource进行数据源动态切换。
首先上applicationContext.xml文件:
- <?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.orghttps://cdn.jxasp.com:9143/image/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xsi:schemaLocation="
- http://www.springframework.org/schema/beans
- classpath:/org/springframework/beans/factory/xml/spring-beans-3.0.xsd
- http://www.springframework.org/schema/aop
- classpath:/org/springframework/aop/config/spring-aop-3.0.xsd
- http://www.springframework.org/schema/context
- classpath:/org/springframework/context/config/spring-context-3.0.xsd
- http://www.springframework.org/schema/tx
- classpath:/org/springframework/transaction/config/spring-tx-3.0.xsd">
-
- <!-- IoC配置 -->
- <!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->
- <context:component-scan base-package="com.shr.dao" />
- <context:component-scan base-package="com.shr.service" />
-
- <!-- DAO配置 -->
- <context:property-placeholder location="classpath:config.properties"/>
- <bean id="mysql" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
- <property name="driverClassName" value="${mysql_driver}"/>
- <property name="url" value="${mysql_url}"/>
- <property name="username" value="${mysql_username}"/>
- <property name="password" value="${mysql_password}"/>
- </bean>
- <bean id="oracle" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
- <property name="driverClassName" value="${ora_driver}"/>
- <property name="url" value="${ora_url}"/>
- <property name="username" value="${ora_username}"/>
- <property name="password" value="${ora_password}"/>
- </bean>
-
- <bean id="dataSource" class="com.shr.dao.datasource.DataSources">
- <property name="targetDataSources">
- <map key-type="java.lang.String">
- <entry value-ref="mysql" key="MYSQL"></entry>
- <entry value-ref="oracle" key="ORACLE"></entry>
- </map>
- </property>
- <property name="defaultTargetDataSource" ref="mysql"></property>
- </bean>
-
- <bean id="vendorProperties"
- class="org.springframework.beans.factory.config.PropertiesFactoryBean">
- <property name="properties">
- <props>
- <prop key="Oracle">oracle</prop>
- <prop key="MySQL">mysql</prop>
- </props>
- </property>
- </bean>
-
- <bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
- <property name="properties" ref="vendorProperties" />
- </bean>
- <bean name="myBatisSQLInterceptor" class="com.shr.dao.MyBatisSQLInterceptor"></bean>
- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <property name="typeAliasesPackage" value="com.shr.dao.pojo,com.shr.dao.model" />
- <property name="databaseIdProvider" ref="databaseIdProvider" />
- <property name="mapperLocations">
- <list>
- <value>classpath:com/shr/dao/resources/mappers/*_mapper.xml</value>
- </list>
- </property>
- <!-- <property name="configLocation" value="/WEB-INF/mybatis-config.xml"/> -->
- <property name="typeHandlersPackage" value="com.shr.dao" />
- <property name="plugins">
- <list>
- <ref bean="myBatisSQLInterceptor"/>
- </list>
- </property>
- </bean>
-
- <!-- 配置事务管理器 -->
- <tx:annotation-driven/>
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="${dataSource}"/>
- </bean>
-
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="com.shr.dao.mapper"/>
- <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
- <!-- <property name="markerInterface" value="com.shr.dao.mapper.ITemplateMapper"/> -->
- </bean>
- </beans>
我们可以观察到文件中多了一段:
- <bean id="dataSource" class="com.shr.dao.datasource.DataSources">
- <property name="targetDataSources">
- <map key-type="java.lang.String">
- <entry value-ref="mysql" key="MYSQL"></entry>
- <entry value-ref="oracle" key="ORACLE"></entry>
- </map>
- </property>
- <property name="defaultTargetDataSource" ref="mysql"></property>
- </bean>
而且sqlSessionFactory的dataSource是关联到上面这段内容的,而不是通过${dataSource}读取config.properties文件的内容获取的。
这个com.shr.dao.datasource.DataSources是自定义的类,继承自AbstractRoutingDataSource类,实现其determineCurrentLookupKey()方法。
代码如下:
- package com.shr.dao.datasource;
- import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
- public class DataSources extends AbstractRoutingDataSource
- {
- @Override
- protected Object determineCurrentLookupKey()
- {
- return DataSourceSwitch.getDataSourceType();
- }
- }
- package com.shr.dao.datasource;
-
- public class DataSourceSwitch
- {
- private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
-
- public static void setDataSourceType(String dataSourceType)
- {
- contextHolder.set(dataSourceType);
- }
-
- public static String getDataSourceType()
- {
- return contextHolder.get();
- }
-
- public static void clearDataSourceType()
- {
- contextHolder.remove();
- }
- }
- package com.shr.dao.datasource;
-
- public class DataSourceInstances
- {
- public static final String MYSQL="MYSQL";
- public static final String ORACLE="ORACLE";
- }
同样,我们通过一个junit测试用例进行验证:
- package com.shr.dao.datasource;
-
- import java.util.List;
-
- import javax.inject.Inject;
-
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.test.context.ContextConfiguration;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
- import org.springframework.test.context.transaction.TransactionConfiguration;
- import org.springframework.transaction.annotation.Transactional;
-
- import com.shr.dao.datasource.DataSourceInstances;
- import com.shr.dao.datasource.DataSourceSwitch;
- import com.shr.dao.model.userManage.UserListInfo;
- import com.shr.service.userManage.UserManageService;
-
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration("file:WebContent/WEB-INF/applicationContext.xml")
- @Transactional
- @TransactionConfiguration(transactionManager="transactionManager",defaultRollback=false)
- public class DynamicDataSourceTest
- {
- @Inject
- private UserManageService userManageService;
-
- @Test
- public void test()
- {
- DataSourceSwitch.setDataSourceType(DataSourceInstances.MYSQL);
- List<UserListInfo> list = userManageService.getUserListInfo();
- for(UserListInfo user : list)
- {
- System.out.println(user.getUser_name());
- }
- }
- }
通过改变DataSourceSwitch.setDataSourceType(DataSourceInstances.ORACLE);可以转换不同的数据源.
欢迎跳转到本文的原文链接:https://honeypps.com/java/spring-mybatis-multi-datasource-props-4/
欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。