基于Spring框架的简单多数据源切换解决办法
基于Spring框架的简单多数据源切换解决办法
Spring框架JDBC包提供了一个抽象类AbstractRoutingDataSource提供了动态切换数据库的基础方法。我们仅仅需要实现一个简单的数据源选择算法就可以轻松的利用Spring框架实现数据源切换了。
Spring支持每次被操作的单数据源的事务。
1.继承AbstractRoutingDataSource并实现方法determineCurrentLookupKey()
1 package dev.tinyz.datasource; 2 3 import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; 4 5 /** 6 * Created by TinyZ on 2014/7/28. 7 */ 8 public class MultiDataSource extends AbstractRoutingDataSource { 9 @Override 10 protected Object determineCurrentLookupKey() { 11 return MultiContextHolder.getDataSourceType(); 12 } 13 }
2.实现一个数据源选择算法。示例提供了一个简单的代码选择数据源示例
1 package dev.tinyz.datasource; 2 3 /** 4 * Created by TinyZ on 2014/7/28. 5 */ 6 public class MultiContextHolder { 7 8 // 定义数据源 - 每个数据源都要在这里注册 9 public static final String DATA_SOURCE_1 = "1";// 对应在beans.xml里面注册的数据源的key 10 public static final String DATA_SOURCE_2 = "2"; 11 12 // ThreadLocal:用于解决线程安全问题。每个线程都会拥有一个独立的变量副本。线程内部可以独立的改变,而不影响其他线程 13 public static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); 14 15 public static void setDataSourceType(String type) { 16 contextHolder.set(type); 17 } 18 19 public static String getDataSourceType() { 20 return contextHolder.get(); 21 } 22 }
3.Spring配置(仅供参考) **最重要的部分 - 包含了定义多数据源,配置多数据源路由器,设置事务支持
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" 4 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" 5 xsi:schemaLocation=" 6 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 7 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 8 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 9 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> 10 11 <!-- Configure all properties files here, wildcards like *.properties are also allowed --> 12 <!-- <context:property-placeholder location="file:conf/conf.properties" /> --> 13 14 <!-- 设置数据源 --><!-- BoneCP configuration --> 15 <bean id="dataSource1" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> 16 <property name="driverClass" value="com.mysql.jdbc.Driver" /> 17 <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/black?useUnicode=true&characterEncoding=UTF-8" /> 18 <property name="username" value="root" /> 19 <property name="password" value="" /> 20 <property name="idleConnectionTestPeriodInMinutes" value="60" /> 21 <property name="idleMaxAgeInMinutes" value="240" /> 22 <property name="maxConnectionsPerPartition" value="10" /> 23 <property name="minConnectionsPerPartition" value="5" /> 24 <property name="partitionCount" value="5" /> 25 <property name="acquireIncrement" value="5" /> 26 <property name="statementsCacheSize" value="100" /> 27 <!--<property name="releaseHelperThreads" value="3" />--> 28 </bean> 29 <bean id="dataSource2" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> 30 <property name="driverClass" value="com.mysql.jdbc.Driver" /> 31 <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/black1?useUnicode=true&characterEncoding=UTF-8" /> 32 <property name="username" value="root" /> 33 <property name="password" value="" /> 34 <property name="idleConnectionTestPeriodInMinutes" value="60" /> 35 <property name="idleMaxAgeInMinutes" value="240" /> 36 <property name="maxConnectionsPerPartition" value="10" /> 37 <property name="minConnectionsPerPartition" value="5" /> 38 <property name="partitionCount" value="5" /> 39 <property name="acquireIncrement" value="5" /> 40 <property name="statementsCacheSize" value="100" /> 41 <!--<property name="releaseHelperThreads" value="3" />--> 42 </bean> 43 44 <!-- 设置abstractRoutingDataSource注入两个变量 --> 45 <bean id="dataSource" class="dev.tinyz.datasource.MultiDataSource"> 46 <property name="targetDataSources"> 47 <map key-type="java.lang.String"> 48 <entry key="1" value-ref="dataSource1"></entry> 49 <entry key="2" value-ref="dataSource2"></entry> 50 </map> 51 </property> 52 <property name="defaultTargetDataSource" ref="dataSource1"/> 53 </bean> 54 55 <!-- 设置缓存工厂 - 数据来源于 dataSource --> 56 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 57 <property name="dataSource" ref="dataSource" /> 58 </bean> 59 <!-- Spring框架 数据库 JDBC事务管理器 --> 60 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 61 <property name="dataSource" ref="dataSource" /> 62 </bean> 63 <!-- Spring框架 事务模板 --> 64 <bean id="txTemplate" class="org.springframework.transaction.support.TransactionTemplate"> 65 <property name="transactionManager" ref="txManager"></property> 66 <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"></property> 67 </bean> 68 <!-- Spring框架 启动使用注解实现声明式事务管理的支持 --> 69 <tx:annotation-driven transaction-manager="txManager" /> 70 71 <!-- Server beans --> 72 73 <!-- 配置容器 不需要任何属性 The Spring application context--> 74 <bean id="springContext" class="dev.tinyz.config.AppContext"></bean> 75 76 <!-- Mybatis Bean --> 77 <bean id="baseMapper" class="org.mybatis.spring.mapper.MapperFactoryBean" abstract="true" lazy-init="true"> 78 <property name="sqlSessionFactory" ref="sqlSessionFactory"/> 79 </bean> 80 <bean id="useMapper" parent="baseMapper"> 81 <property name="mapperInterface" value="dev.tinyz.persistence.mapper.UserMapper"/> 82 </bean> 83 84 <!-- 注解配置 --> 85 <context:annotation-config /> 86 <!-- 注解扫描 基础包-dev.tinyz.persistence --> 87 <context:component-scan base-package="dev.tinyz.persistence" /> 88 </beans>
dataSource 是我们定义的MultiDataSource的实例。拥有两个属性targetDataSources和defaultTargetDataSource,这两个属性名都不能修改。因为AbstractRoutingDataSource里面设置的参数是依赖Spring注入的。有需要的朋友可以去查看Spring的源码
AppContext 是程序实现的Spring单例。继承ApplicationContextAware
baseMapper 定义了Mybatis-Spring桥里面的一个抽象类。用于子类实现映射接口
4.简单的测试代码(示例)
1 // 测试 2 final UserMapper userMapper = (UserMapper) AppContext.getBean("useMapper"); 3 // 切换到数据源1 4 MultiContextHolder.setDataSourceType(MultiContextHolder.DATA_SOURCE_1); 5 // 查询数据库 6 MemUser tinyz1 = userMapper.selectByAccount("tinyz1");
ps:以下的内容是笔者提供的示例。假如不需要的话,可以忽略。O(∩_∩)O哈哈~。写的很简单。
示例的需求:
操作系统:Win 7 64bit
编辑工具:Intellij IDEA 13.1
数据库: MYSQL 5.6
ps:使用IDEA导出了一份eclipse的配置。但是不知道能不能用eclipse打开。。未测试
类库依赖:
BoneCp 0.8.0
Mybatis 3.2.7
Mybatis-Spring 1.2.2
SpringFramework 3.2.10
Mysql-Connecter-java 3.1.31
ps:所有的依赖全部都是依靠Maven的。所以你懂的。
Main就是实例的测试代码。beans.xml配置文件里面的各个数据源的访问地址,账户和密码。自行修改
示例源代码下载地址:示例-基于Spring框架的简单多数据源切换解决办法
作者:TinyZ
出处:http://www.cnblogs.com/zou90512/
关于作者:努力学习,天天向上。不断探索学习,提升自身价值。记录经验分享。
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接
如有问题,可以通过 zou90512@126.com 联系我,非常感谢。
笔者网店: http://aoleitaisen.taobao.com. 欢迎广大读者围观