关键词搜索

源码搜索 ×
×

Spring+Mybatis多数据源配置(四)——AbstractRoutingDataSource实现数据源动态切换

发布2015-11-20浏览12951次

详情内容

欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。

欢迎跳转到本文的原文链接:https://honeypps.com/java/spring-mybatis-multi-datasource-props-4/

有时候需要在程序中动态切换数据源,那么这个系列的之前的博文所阐述的方法就不再使用了,总不能通过程序更改config.properties文件的dataSource的值,然后再重启web服务器以便加载applicationContext.xml文件。这里讲诉的是如何利用AbstractRoutingDataSource进行数据源动态切换。

首先上applicationContext.xml文件:

 

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.orghttps://cdn.jxasp.com:9143/image/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xmlns:aop="http://www.springframework.org/schema/aop"
  6. xmlns:tx="http://www.springframework.org/schema/tx"
  7. xsi:schemaLocation="
  8. http://www.springframework.org/schema/beans
  9. classpath:/org/springframework/beans/factory/xml/spring-beans-3.0.xsd
  10. http://www.springframework.org/schema/aop
  11. classpath:/org/springframework/aop/config/spring-aop-3.0.xsd
  12. http://www.springframework.org/schema/context
  13. classpath:/org/springframework/context/config/spring-context-3.0.xsd
  14. http://www.springframework.org/schema/tx
  15. classpath:/org/springframework/transaction/config/spring-tx-3.0.xsd">
  16. <!-- IoC配置 -->
  17. <!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 -->
  18. <context:component-scan base-package="com.shr.dao" />
  19. <context:component-scan base-package="com.shr.service" />
  20. <!-- DAO配置 -->
  21. <context:property-placeholder location="classpath:config.properties"/>
  22. <bean id="mysql" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  23. <property name="driverClassName" value="${mysql_driver}"/>
  24. <property name="url" value="${mysql_url}"/>
  25. <property name="username" value="${mysql_username}"/>
  26. <property name="password" value="${mysql_password}"/>
  27. </bean>
  28. <bean id="oracle" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  29. <property name="driverClassName" value="${ora_driver}"/>
  30. <property name="url" value="${ora_url}"/>
  31. <property name="username" value="${ora_username}"/>
  32. <property name="password" value="${ora_password}"/>
  33. </bean>
  34. <bean id="dataSource" class="com.shr.dao.datasource.DataSources">
  35. <property name="targetDataSources">
  36. <map key-type="java.lang.String">
  37. <entry value-ref="mysql" key="MYSQL"></entry>
  38. <entry value-ref="oracle" key="ORACLE"></entry>
  39. </map>
  40. </property>
  41. <property name="defaultTargetDataSource" ref="mysql"></property>
  42. </bean>
  43. <bean id="vendorProperties"
  44. class="org.springframework.beans.factory.config.PropertiesFactoryBean">
  45. <property name="properties">
  46. <props>
  47. <prop key="Oracle">oracle</prop>
  48. <prop key="MySQL">mysql</prop>
  49. </props>
  50. </property>
  51. </bean>
  52. <bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
  53. <property name="properties" ref="vendorProperties" />
  54. </bean>
  55. <bean name="myBatisSQLInterceptor" class="com.shr.dao.MyBatisSQLInterceptor"></bean>
  56. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  57. <property name="dataSource" ref="dataSource" />
  58. <property name="typeAliasesPackage" value="com.shr.dao.pojo,com.shr.dao.model" />
  59. <property name="databaseIdProvider" ref="databaseIdProvider" />
  60. <property name="mapperLocations">
  61. <list>
  62. <value>classpath:com/shr/dao/resources/mappers/*_mapper.xml</value>
  63. </list>
  64. </property>
  65. <!-- <property name="configLocation" value="/WEB-INF/mybatis-config.xml"/> -->
  66. <property name="typeHandlersPackage" value="com.shr.dao" />
  67. <property name="plugins">
  68. <list>
  69. <ref bean="myBatisSQLInterceptor"/>
  70. </list>
  71. </property>
  72. </bean>
  73. <!-- 配置事务管理器 -->
  74. <tx:annotation-driven/>
  75. <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  76. <property name="dataSource" ref="${dataSource}"/>
  77. </bean>
  78. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  79. <property name="basePackage" value="com.shr.dao.mapper"/>
  80. <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
  81. <!-- <property name="markerInterface" value="com.shr.dao.mapper.ITemplateMapper"/> -->
  82. </bean>
  83. </beans>

我们可以观察到文件中多了一段:

 

 

  1. <bean id="dataSource" class="com.shr.dao.datasource.DataSources">
  2. <property name="targetDataSources">
  3. <map key-type="java.lang.String">
  4. <entry value-ref="mysql" key="MYSQL"></entry>
  5. <entry value-ref="oracle" key="ORACLE"></entry>
  6. </map>
  7. </property>
  8. <property name="defaultTargetDataSource" ref="mysql"></property>
  9. </bean>

而且sqlSessionFactory的dataSource是关联到上面这段内容的,而不是通过${dataSource}读取config.properties文件的内容获取的。

 

这个com.shr.dao.datasource.DataSources是自定义的类,继承自AbstractRoutingDataSource类,实现其determineCurrentLookupKey()方法。

代码如下:

 

  1. package com.shr.dao.datasource;
  2. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
  3. public class DataSources extends AbstractRoutingDataSource
  4. {
  5. @Override
  6. protected Object determineCurrentLookupKey()
  7. {
  8. return DataSourceSwitch.getDataSourceType();
  9. }
  10. }
  1. package com.shr.dao.datasource;
  2. public class DataSourceSwitch
  3. {
  4. private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
  5. public static void setDataSourceType(String dataSourceType)
  6. {
  7. contextHolder.set(dataSourceType);
  8. }
  9. public static String getDataSourceType()
  10. {
  11. return contextHolder.get();
  12. }
  13. public static void clearDataSourceType()
  14. {
  15. contextHolder.remove();
  16. }
  17. }
  1. package com.shr.dao.datasource;
  2. public class DataSourceInstances
  3. {
  4. public static final String MYSQL="MYSQL";
  5. public static final String ORACLE="ORACLE";
  6. }

同样,我们通过一个junit测试用例进行验证:

 

 

  1. package com.shr.dao.datasource;
  2. import java.util.List;
  3. import javax.inject.Inject;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.test.context.ContextConfiguration;
  7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  8. import org.springframework.test.context.transaction.TransactionConfiguration;
  9. import org.springframework.transaction.annotation.Transactional;
  10. import com.shr.dao.datasource.DataSourceInstances;
  11. import com.shr.dao.datasource.DataSourceSwitch;
  12. import com.shr.dao.model.userManage.UserListInfo;
  13. import com.shr.service.userManage.UserManageService;
  14. @RunWith(SpringJUnit4ClassRunner.class)
  15. @ContextConfiguration("file:WebContent/WEB-INF/applicationContext.xml")
  16. @Transactional
  17. @TransactionConfiguration(transactionManager="transactionManager",defaultRollback=false)
  18. public class DynamicDataSourceTest
  19. {
  20. @Inject
  21. private UserManageService userManageService;
  22. @Test
  23. public void test()
  24. {
  25. DataSourceSwitch.setDataSourceType(DataSourceInstances.MYSQL);
  26. List<UserListInfo> list = userManageService.getUserListInfo();
  27. for(UserListInfo user : list)
  28. {
  29. System.out.println(user.getUser_name());
  30. }
  31. }
  32. }

通过改变DataSourceSwitch.setDataSourceType(DataSourceInstances.ORACLE);可以转换不同的数据源.

欢迎跳转到本文的原文链接:https://honeypps.com/java/spring-mybatis-multi-datasource-props-4/

欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。

相关技术文章

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载