浅谈Spring+Mybatis的数据源动态切换

这个问题困扰我好几天,今天稍微总结一下,以后还得继续 deep dig。不过,今天长沙的阳光真的是甚好啊!

首先,说说这个数据源切换的使用情景:因为项目用到了多个数据源的数据,有时候得切换一下数据源,去另外一个数据源下获取数据。

 

 那么代码到底要怎么写呢?

自定义一个类去继承AbstractRoutingDataSource类并重写其determineCurrentLookupKey()方法

先直接贴我项目中的代码:

一:首先是spring中的数据源配置:

数据源的实现类是 DynamicDataSource ,等下会介绍

 然后是两个数据源的配置 :dictdataSource 和defaultdataSource

 二:DynamicDataSource 

package com.zhiguangyun.modules.empi.util;


/**
 * 实现数据库的动态切换
 */
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource{

	@Override
	protected Object determineCurrentLookupKey() {
		return getDataSourceType();
	}
  
	private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
	/**
	 * @Description: 设置数据源类型
	 * @param dataSourceType  数据库类型
	 * @return void
	 * @throws
	 */
	public static void setDataSourceType(String dataSourceType) {
		contextHolder.set(dataSourceType);
	}
	
	/**
	 * @Description: 获取数据源类型
	 * @param 
	 * @return String
	 * @throws
	 */
	public static String getDataSourceType() {
		return contextHolder.get();
	}
	
	/**
	 * @Description: 清除数据源类型
	 * @param 
	 * @return void
	 * @throws
	 */
	public static void clearDataSourceType() {
		contextHolder.remove();
	}
	

}

关键代码:

三.调用切换数据源的代码

 

以上就是我项目中实现数据源切换的代码,然后就聊一下这个流程。

首先   DynamicDataSource 继承了AbstractRoutingDataSource 类, 并实现其抽象方法determineCurrentLookupKey()

 AbstractRoutingDataSource 继承了 AbstractDataSource类 并且实现了 InitializingBean接口

那么InitializingBean 接口又有什么属性呢?

InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是实现该接口的类,在初始化bean的时候都会执行该方法。这个afterPropertiesSet  方法 甚至 先于 init-method 方法执行。那么当在spring配置中数据源初始化的时候,它就会去调用 afterPropertiesSet 方法。

这是AbstractRoutingDataSource 类中,重写的afterPropertiesSet()方法

从上面可以看到,它将 我们在 spring中配置的 两个数据源的信息存入了 resolveDataSources这个map中,回顾一下先前代码:

(1)AbstractRoutingDataSource 的属性  

(2)spring 中的数据源配置

 spring 的配置中是将 默认数据源信息存到了 key值为 defaultTargetDataSource 的map中,而要切换的数据源信息存到了key值为 targetDataSources 的map中,这和AbstractRoutingDataSource类中的属性是对应的。当spring 初始化 完bean的属性后,就会调用afterPropertiesSet这个方法,然后将 数据源的信息又存到了 resolveDataSources 这个map中,方便后面根据key从这个map中拿dataSource。

Mybatis只有在真正执行sql操作的时候才会去获取数据库连接。我们看下DataSource中 Connection getConnection() throws SQLException;是如何实现的:

关键在于 determineTargetDataSource()方法中用到了 determineCurrentLookupKey()方法,而determineCurrentLookupKey()是一个抽象方法,要子类是实现。其实这里,就是数据源切换的核心代码了,因为这里返回一个你要切换的数据源去connection。

Object lookupKey = determineCurrentLookupKey();determineCurrentLookupKey()方法是我们DynamicDataSource类实现的。

切换数据源的时候,首先将要切换的那个数据源的名字  通过 setDataSource中,也就是存到ThreadLocal中。然后  determineCurrentLookupKey 再去获取ThreadLocal中保存的 key 值。拿到了这个要切换的key(也就是那个数据源的名字)之后, 再从afterPropertiesSet()中存储好了的resolvedDataSources这个map中获得key对应的dataSource,再返回给  Connection getConnection()去进行数据源的连接。

这就是整个数据源切换的流程。

其实 ,由于基础不是很好,对于这个流程,我自己还有些地方比较困惑,希望看到我这篇博客的朋友,可以指正。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一彡十

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值