基于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 }
View Code

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 }
View Code

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&amp;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&amp;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>
View Code
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");
View Code

 

 

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. 欢迎广大读者围观

 

posted @ 2014-07-30 16:27  Tiny&zzh  阅读(830)  评论(0编辑  收藏  举报