spring+mybatis多数据源动态切换
spring mvc+mybatis+多数据源切换 选取oracle,mysql作为例子切换数据源。oracle为默认数据源,在测试的action中,进行mysql和oracle的动态切换。
web.xml
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>trac</param-value>
</context-param> <!-- Spring的log4j监听器 -->
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener> <!-- 字符集 过滤器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- Spring view分发器 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping> <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
applicationContext.xml
<bean id="parentDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
</bean> <bean id="mySqlDataSource" parent="parentDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean> <bean id="oracleDataSource" parent="parentDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url" value="jdbc:oracle:thin:@10.16.17.40:1531:addb"></property>
<property name="username" value="trac"></property>
<property name="password" value="trac"></property>
</bean> <bean id="dataSource" class="com.trac.dao.datasource.DataSources">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="mySqlDataSource" key="MYSQL"></entry>
<entry value-ref="oracleDataSource" key="ORACLE"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="oracleDataSource"></property>
</bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> <!-- 创建SqlSessionFactory,同时指定数据源和mapper -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath*:com/trac/ibatis/dbcp/*.xml" />
</bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.trac.dao" />
</bean>
配置 parentDataSource 的父bean.再配置多个数据源继承这个父bean,对driverClass,url,username,password,等数据源连接参数进行各自的重写。例如 mySqlDataSource ,在 DataSources bean中注入所有要切换的数据源,并且设置默认的数据源。
DataSourceInstances.java
public class DataSourceInstances{
public static final String MYSQL="MYSQL";
public static final String ORACLE="ORACLE";
}
DataSourceSwitch.java
public class DataSourceSwitch{
private static final ThreadLocal contextHolder=new ThreadLocal();
public static void setDataSourceType(String dataSourceType){
contextHolder.set(dataSourceType);
}
public static String getDataSourceType(){
return (String) contextHolder.get();
}
public static void clearDataSourceType(){
contextHolder.remove();
}
}
DataSources.java
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DataSources extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitch.getDataSourceType();
}
}
测试
@Controller
@SuppressWarnings("unused")
public class TestAction {
@Autowired
TestMapper testMapper; @RequestMapping("/test.action")
public ModelAndView test(
HttpServletRequest request,
HttpServletResponse resp){
ModelAndView model = new ModelAndView("test");
model.addObject("test1", "这是一个测试,获取默认数据连接MYSQL:"+testMapper.test());
DataSourceSwitch.setDataSourceType(DataSourceInstances.ORACLE);
model.addObject("test2", "这是一个测试,获取数据连接ORACLE:"+testMapper.test());
DataSourceSwitch.setDataSourceType(DataSourceInstances.MYSQL);
model.addObject("test3", "这是一个测试,获取数据连接MYSQL:"+testMapper.test());
return model;
}
}
代码解释:
查看AbstractRoutingDataSource中的获取数据库连接源码
public Connection getConnection()
throws SQLException
{
return determineTargetDataSource().getConnection();
}
查看determineTargetDataSource方法
protected DataSource determineTargetDataSource()
{
Assert.notNull(resolvedDataSources, "DataSource router not initialized");
Object lookupKey = determineCurrentLookupKey();
DataSource dataSource = (DataSource)resolvedDataSources.get(lookupKey);
if(dataSource == null && (lenientFallback || lookupKey == null))
dataSource = resolvedDefaultDataSource;
if(dataSource == null)
throw new IllegalStateException((new StringBuilder()).append("Cannot determine target DataSource for lookup key [").append(lookupKey).append("]").toString());
else
return dataSource;
}
其中DataSource dataSource = (DataSource)resolvedDataSources.get(lookupKey); 中的resolvedDataSources 就是我们spring中设置的targetDataSources,是一个Map类型,里面有我们设置的MYSQL和ORACLE数据库连接池
注意determineCurrentLookupKey方法,
protected abstract Object determineCurrentLookupKey();
是一个抽象方法,需要我们去实现,我们将数据源对应的KEY放在本地线程中,那么可以随时在代码中进行切换数据源
默认数据源
在spring配置文件中,我们将defaultTargetDataSource注入到AbstractRoutingDataSource中
public void afterPropertiesSet()
{
if(targetDataSources == null)
throw new IllegalArgumentException("Property 'targetDataSources' is required");
resolvedDataSources = new HashMap(targetDataSources.size());
Object lookupKey;
DataSource dataSource;
for(Iterator iterator = targetDataSources.entrySet().iterator(); iterator.hasNext(); resolvedDataSources.put(lookupKey, dataSource))
{
java.util.Map.Entry entry = (java.util.Map.Entry)iterator.next();
lookupKey = resolveSpecifiedLookupKey(entry.getKey());
dataSource = resolveSpecifiedDataSource(entry.getValue());
} if(defaultTargetDataSource != null)
resolvedDefaultDataSource = resolveSpecifiedDataSource(defaultTargetDataSource);
}
AbstractRoutingDataSource类实现了InitializingBean接口,项目启动会实现方法afterPropertiesSet,生成resolvedDefaultDataSource实例,这样在determineTargetDataSource方法中如果获取本地线程变量中的连接位空,那么就选择默认数据源。
spring+mybatis多数据源动态切换的更多相关文章
- mybatis 多数据源动态切换
笔者主要从事c#开发,近期因为项目需要,搭建了一套spring-cloud微服务框架,集成了eureka服务注册中心. gateway网关过滤.admin服务监控.auth授权体系验证,集成了redi ...
- Spring + Mybatis 项目实现动态切换数据源
项目背景:项目开发中数据库使用了读写分离,所有查询语句走从库,除此之外走主库. 最简单的办法其实就是建两个包,把之前数据源那一套配置copy一份,指向另外的包,但是这样扩展很有限,所有采用下面的办法. ...
- 170615、spring不同数据库数据源动态切换
spring mvc+mybatis+多数据源切换 选取Oracle,MySQL作为例子切换数据源.mysql为默认数据源,在测试的action中,进行mysql和oracle的动态切换. 1.web ...
- springboot多数据源动态切换和自定义mybatis分页插件
1.配置多数据源 增加druid依赖 完整pom文件 数据源配置文件 route.datasource.driver-class-name= com.mysql.jdbc.Driver route.d ...
- Spring多数据源动态切换
title: Spring多数据源动态切换 date: 2019-11-27 categories: Java Spring tags: 数据源 typora-root-url: ...... --- ...
- 实战:Spring AOP实现多数据源动态切换
需求背景 去年底,公司项目有一个需求中有个接口需要用到平台.算法.大数据等三个不同数据库的数据进行计算.组装以及最后的展示,当时这个需求是另一个老同事在做,我只是负责自己的部分. 直到今年回来了,这个 ...
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源方法
一.开篇 这里整合分别采用了Hibernate和MyBatis两大持久层框架,Hibernate主要完成增删改功能和一些单一的对象查询功能,MyBatis主要负责查询功能.所以在出来数据库方言的时候基 ...
- Springboot多数据源配置--数据源动态切换
在上一篇我们介绍了多数据源,但是我们会发现在实际中我们很少直接获取数据源对象进行操作,我们常用的是jdbcTemplate或者是jpa进行操作数据库.那么这一节我们将要介绍怎么进行多数据源动态切换.添 ...
随机推荐
- 去IOE的一点反对意见以及其他
某天在机场听见两老板在聊天,说到他们目前销售的报表老跟不上的问题,说要请一个人,专门合并和分析一些发过来的excel表格,我真想冲上去说,老板,你需要的是一个信息处理的系统,你需要咨询么.回来一直耿耿 ...
- BPM体系文件管理解决方案分享
一.方案概述 企业管理在很大程度上是通过文件化的形式表现出来,体系文件管理是管理体系存在的基础和证据,是规范企业管理活动和全体人员行为,达到管理目标的管理依据.对与公司质量.环境.职业健康安全等体系有 ...
- Impress.js上手 - 抛开PPT、制作Web 3D幻灯片放映
前言: 如果你已经厌倦了使用PPT设置路径.设置时间.设置动画方式来制作动画特效.那么Impress.js将是你一个非常好的选择. 用它制作的PPT将更加直观.效果也是嗷嗷美观的. 当然,如果用它来装 ...
- CYQ.Data V5 从入门到放弃ORM系列:教程 - MAction类使用
背景: 随着V5框架使用者的快速增加,终于促使我开始对整个框架编写完整的Demo. 上周大概花了一星期的时间,每天写到夜里3点半,终完成了框架所有功能的Demo. 同时,按V5框架名称空间的顺序,对每 ...
- .NET面试题系列[4] - C# 基础知识(2)
2 类型转换 面试出现频率:主要考察装箱和拆箱.对于有笔试题的场合也可能会考一些基本的类型转换是否合法. 重要程度:10/10 CLR最重要的特性之一就是类型安全性.在运行时,CLR总是知道一个对象是 ...
- 【腾讯Bugly干货分享】动态链接库加载原理及HotFix方案介绍
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57bec216d81f2415515d3e9c 作者:陈昱全 引言 随着项目中动 ...
- .NET全栈开发工程师学习路径
PS:最近一直反复地看博客园以前发布的一条.NET全栈开发工程师的招聘启事,觉得这是我看过最有创意也最朴实的一个招聘启事,更为重要的是它更像是一个技术提纲,能够指引我们的学习和提升,现在转载过来与各位 ...
- [Intel Edison开发板] 01、Edison开发板性能简述
Integrated Wi-Fi certified in 68 countries, Bluetooth® 4.0 support, 1GB DDR and 4GB flash memory sim ...
- JavaScript随笔3
1.获取非行间css if(oDiv.currentStyle){ alert(oDiv.currentStyle.width); }else{ alert(oDiv.getComputedStyle ...
- 我为NET狂官方面试题
基础牢不牢测一测便了解,工作没工作测一测便清楚,工作有几年测一测便知道 最近帮人过一遍C#基础,出了点题目,有需要的同志拿走 答案不唯一,官方答案只供参考,若有错误欢迎提出~ 更新ing 1.面向过程 ...