基于Spring框架的简单多数据源切换解决办法

来源:互联网 发布:小区网络装iptv服务器 编辑:程序博客网 时间:2024/06/07 00:14

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     @Override10     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里面注册的数据源的key10     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&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>
复制代码
dataSource 是我们定义的MultiDataSource的实例。拥有两个属性targetDataSources和defaultTargetDataSource,这两个属性名都不能修改。因为AbstractRoutingDataSource里面设置的参数是依赖Spring注入的。有需要的朋友可以去查看Spring的源码
AppContext 是程序实现的Spring单例。继承ApplicationContextAware
baseMapper 定义了Mybatis-Spring桥里面的一个抽象类。用于子类实现映射接口

4.简单的测试代码(示例)

1 // 测试2         final UserMapper userMapper = (UserMapper) AppContext.getBean("useMapper");3         // 切换到数据源14         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框架的简单多数据源切换解决办法

0 0
原创粉丝点击