基于Spring框架的简单多数据源切换解决办法
基于Spring框架的简单多数据源切换解决办法
Spring框架JDBC包提供了一个抽象类AbstractRoutingDataSource提供了动态切换数据库的基础方法。我们仅仅需要实现一个简单的数据源选择算法就可以轻松的利用Spring框架实现数据源切换了。
Spring支持每次被操作的单数据源的事务。
1.继承AbstractRoutingDataSource并实现方法determineCurrentLookupKey()
package dev.tinyz.datasource; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /**
* Created by TinyZ on 2014/7/28.
*/
public class MultiDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return MultiContextHolder.getDataSourceType();
}
}
2.实现一个数据源选择算法。示例提供了一个简单的代码选择数据源示例
package dev.tinyz.datasource; /**
* Created by TinyZ on 2014/7/28.
*/
public class MultiContextHolder { // 定义数据源 - 每个数据源都要在这里注册
public static final String DATA_SOURCE_1 = "1";// 对应在beans.xml里面注册的数据源的key
public static final String DATA_SOURCE_2 = "2"; // ThreadLocal:用于解决线程安全问题。每个线程都会拥有一个独立的变量副本。线程内部可以独立的改变,而不影响其他线程
public static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setDataSourceType(String type) {
contextHolder.set(type);
} public static String getDataSourceType() {
return contextHolder.get();
}
}
3.Spring配置(仅供参考) **最重要的部分 - 包含了定义多数据源,配置多数据源路由器,设置事务支持
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> <!-- Configure all properties files here, wildcards like *.properties are also allowed -->
<!-- <context:property-placeholder location="file:conf/conf.properties" /> --> <!-- 设置数据源 --><!-- BoneCP configuration -->
<bean id="dataSource1" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/black?useUnicode=true&characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="" />
<property name="idleConnectionTestPeriodInMinutes" value="60" />
<property name="idleMaxAgeInMinutes" value="240" />
<property name="maxConnectionsPerPartition" value="10" />
<property name="minConnectionsPerPartition" value="5" />
<property name="partitionCount" value="5" />
<property name="acquireIncrement" value="5" />
<property name="statementsCacheSize" value="100" />
<!--<property name="releaseHelperThreads" value="3" />-->
</bean>
<bean id="dataSource2" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/black1?useUnicode=true&characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="" />
<property name="idleConnectionTestPeriodInMinutes" value="60" />
<property name="idleMaxAgeInMinutes" value="240" />
<property name="maxConnectionsPerPartition" value="10" />
<property name="minConnectionsPerPartition" value="5" />
<property name="partitionCount" value="5" />
<property name="acquireIncrement" value="5" />
<property name="statementsCacheSize" value="100" />
<!--<property name="releaseHelperThreads" value="3" />-->
</bean> <!-- 设置abstractRoutingDataSource注入两个变量 -->
<bean id="dataSource" class="dev.tinyz.datasource.MultiDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="1" value-ref="dataSource1"></entry>
<entry key="2" value-ref="dataSource2"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSource1"/>
</bean> <!-- 设置缓存工厂 - 数据来源于 dataSource -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Spring框架 数据库 JDBC事务管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Spring框架 事务模板 -->
<bean id="txTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="txManager"></property>
<property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"></property>
</bean>
<!-- Spring框架 启动使用注解实现声明式事务管理的支持 -->
<tx:annotation-driven transaction-manager="txManager" /> <!-- Server beans --> <!-- 配置容器 不需要任何属性 The Spring application context-->
<bean id="springContext" class="dev.tinyz.config.AppContext"></bean> <!-- Mybatis Bean -->
<bean id="baseMapper" class="org.mybatis.spring.mapper.MapperFactoryBean" abstract="true" lazy-init="true">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="useMapper" parent="baseMapper">
<property name="mapperInterface" value="dev.tinyz.persistence.mapper.UserMapper"/>
</bean> <!-- 注解配置 -->
<context:annotation-config />
<!-- 注解扫描 基础包-dev.tinyz.persistence -->
<context:component-scan base-package="dev.tinyz.persistence" />
</beans>
dataSource 是我们定义的MultiDataSource的实例。拥有两个属性targetDataSources和defaultTargetDataSource,这两个属性名都不能修改。因为AbstractRoutingDataSource里面设置的参数是依赖Spring注入的。有需要的朋友可以去查看Spring的源码
AppContext 是程序实现的Spring单例。继承ApplicationContextAware
baseMapper 定义了Mybatis-Spring桥里面的一个抽象类。用于子类实现映射接口
4.简单的测试代码(示例)
// 测试
final UserMapper userMapper = (UserMapper) AppContext.getBean("useMapper");
// 切换到数据源1
MultiContextHolder.setDataSourceType(MultiContextHolder.DATA_SOURCE_1);
// 查询数据库
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. 欢迎广大读者围观
基于Spring框架的简单多数据源切换解决办法的更多相关文章
- 基于Spring框架应用的权限控制系统的研究和实现
摘 要: Spring框架是一个优秀的多层J2EE系统框架,Spring本身没有提供对系统的安全性支持.Acegi是基于Spring IOC 和 AOP机制实现的一个安全框架.本文探讨了Acegi安全 ...
- 基于ThinkPHP框架的简单的后台管理系统
版权声明:本文为博主原创文章,未经博主允许不得转载. 基于ThinkPHP框架的简单的后台管理系统 一个简单的后台管理系统,可能还不全面,可以自己改,有登录功能 实例如图:
- Eclipse IDE下的Spring框架使用简单实例
Eclipse IDE下的Spring框架使用简单实例 1 准备Java jdk安装. Eclipse软件安装.根据系统安装32/64版本,选择Eclipse IDE for Java Develop ...
- 在vue中使用 layui框架中的form.render()无效解决办法
下面简单介绍在vue中使用 layui框架中的form.render()无效解决办法. 原文地址:小时刻个人技术博客 > http://small.aiweimeng.top/index.php ...
- 第一次玩博客,今天被安利了一个很方便JDBC的基于Spring框架的一个叫SimpleInsert的类,现在就来简单介绍一下
首先先对这段代码的简单介绍,我之前在需要操作JDBC的时候总是会因为经常要重新写SQL语句感到很麻烦.所以就能拿则拿不能拿的就简单地封装了一下. 首先是Insert.Spring框架的JDBC包里面的 ...
- 30个类手写Spring核心原理之动态数据源切换(8)
本文节选自<Spring 5核心原理> 阅读本文之前,请先阅读以下内容: 30个类手写Spring核心原理之自定义ORM(上)(6) 30个类手写Spring核心原理之自定义ORM(下)( ...
- 基于Spring框架怎么构建游戏玩法服务
说明:本篇阐述的问题,是基于前面的游戏服务器架构设计的. 问题 众所周知,Spring最擅长的领域是无状态服务的构建,而游戏(尤其是玩法部分)是有状态的.以棋牌游戏为例,玩法服务里面大概涉及以下两类对 ...
- 【Spring】使用Spring的AbstractRoutingDataSource实现多数据源切换
最近因为项目需要在做两个项目间数据同步的需求,具体是项目1的数据通过消息队列同步到项目2中,因为这个更新操作还涉及到更新多个库的数据,所以就需要多数据源切换的操作.下面就讲讲在Spring中如何进行数 ...
- 使用Spring的AbstractRoutingDataSource实现多数据源切换
https://www.cnblogs.com/softidea/p/7127874.html?utm_source=itdadao&utm_medium=referral https://b ...
随机推荐
- 流畅的python第十九章元编程学习记录
在 Python 中,数据的属性和处理数据的方法统称属性(attribute).其实,方法只是可调用的属性.除了这二者之外,我们还可以创建特性(property),在不改变类接口的前提下,使用存取方法 ...
- FXC Define的使用方法
https://docs.microsoft.com/en-us/windows/desktop/direct3dtools/dx-graphics-tools-fxc-syntax https:// ...
- HQL语句中数据类型转换,及hibernate中createQuery执行hql报错
一.HQL语句中数据类型转换: 我们需要从数据库中取出序号最大的记录,想到的方法就是使用order by子句进行排序(desc倒序),然后取出第一个对象,可是当初设计数据库时(我们是在原来的数据库的基 ...
- 更改"xxxx" 的权限: 不允许的操作
[摘要:做为root用户,用chmod为何改没有了文件权限 以ROOT用户上岸,当用chmod改文件权限时,体系表现无权变动,为何 文件名是:aa chmod 777 aa chmod: changi ...
- WinForm客户端调用 WebService时 如何启用Session
WinForm客户端调用 WebService时 如何启用Session 摘自: http://www.cnblogs.com/swtseaman/archive/2011/04/18/2020176 ...
- Solr 中 Schema 结构说明
schema.xml位于solr/conf/目录下,类似于数据表配置文件,定义了加入索引的数据的数据类型,主要包括type.fields和其他的一些缺省设置 1.schema的基本配置 <?xm ...
- JNI_Android项目中调用.so动态库
JNI_Android项目中调用.so动态库 2014年6月3日 JNI学习 參考:http://blog.sina.com.cn/s/blog_4298002e01013zk8.html 上一篇笔者 ...
- CentOS7 Failed to start LSB: Bring up/down networking. 已解决!!!
服务器更换了主板之前配置的静态IP发现启动网卡出现异常. 执行 service network restart 出现以下错误 Restarting network (via systemctl): ...
- C#秘密武器之特性
一.概述 Attribute说白了就是一个类而已,里边一般含有一些附加信息,或者一些特殊的处理逻辑,以便告诉编译器应用该特性的东东是个奇葩,需要特殊对待! 二.使用时的注意事项 2.1. Attrib ...
- js math 对数和指数处理 expm1 log1p
1.Math.expm1() Math.expm1(x)返回 ex - 1,即Math.exp(x) - 1. Math.expm1(-1) // -0.6321205588285577 Math.e ...