前言
记录自己开发过程的解决方法和实现思路:
最近由于关系的原因需要使用多数据源切换进行不同数据库的数据展示和操作,所以进行了研究,并记录整个过程
我所使用的是Mysql5.7版本Spring boot版本为2.1.6。
实现的原理:
使用注解标识要使用的数据源,然后继承AbstractRoutingDataSource再利用AOP在执行方法前切换数据源,数据源是使用的spring提供的多数据源类(org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource)
对多数据源实现的核心类AbstractRoutingDataSource部分内容解析
以上为AbstractRoutingDataSource部分源代码,
其中主要使用为以下方法
- setTargetDataSources(注入目标数据源)
- setDefaultTargetDataSource(注入默认的数据源)
- determineCurrentLookupKey(是一个抽象方法,它由具体的子类实现。这个方法的目的是确定当前线程应该使用的数据源的标识。在实际应用中,这个方法通常通过访问线程本地变量或其他上下文信息来获取标识)
- setTargetDataSources方法–需要切换的数据源,参数为Map,key是determineCurrentLookupKey方法的返回值,value是数据源实例
- setDefaultTargetDataSource方法设置默认使用的数据源,就是没有指定数据源的情况下使用的数据源,参数是一个数据源实例
- 需要进行实现的抽象方法determineCurrentLookupKey(),该方法返回需要使用的DataSource的key值,然后根据这个key从resolvedDataSources这个map里取出对应的DataSource,如果找不到,则用默认的resolvedDefaultDataSource。
目录结构如图所示:
![datasource.png]/blog/java/datasource.png)
主要类的说明:
配置文件以及相关类的说明
- 数据库配置文件:application.yml;
- 数据源注解类:DataSource.java;
- 数据源AOP类:DataSourceAspect.java;
- 数据源Bean配置类:DataSourceBean.java;
- 数据库配置类:DataSourceConfig.java;
- 数据源工具:DataSourceUtil.java;
- 多数据源类型:DataSourceType.java;
- 实现AOP动态切换:DynamicDataSource.java;
- 定义上下文数据源:JdbcContextHolder.java;
启动项目之前需要将自带的数据源进行排除:
数据库配置文件:application.yml
具体的代码如下:
数据源注解类:DataSource.java
1 | import java.lang.annotation.ElementType; |
数据源AOP类:DataSourceAspect.java
1 |
|
数据源Bean配置:DataSourceBean.java
1 |
|
数据库配置类:DataSourceConfig.java
1 |
|
数据源工具:DataSourceUtil.java
1 |
|
多数据源类型:DataSourceType.java
1 | /** |
实现AOP动态切换:DynamicDataSource.java
1 |
|
定义上下文数据源:JdbcContextHolder.java
1 |
|
数据源配置已经完成,如果在代码中进行使用如图
数据源的切换我选择在Service层进行,如果在controller进行切换的话,单一不灵活,而选择在Service层进行,只需要在controller里面注入多个service实现即可,如果开启了事务的话,需要在事务执行之前将数据进行切换,否则会出现数据源切换失败,原因:事务本身也是通过AOP配置的,因为它先走了事务切面,在事务还未结束的时候去切换数据源的话会出错的,设置一下切换数据源的AOP的优先级,确保在事务执行之前就已经切换数据源。进行测试,没有发现问题。
数据源动态切换已经完成。
结语
此篇内容仅仅只是记录自己在完成该功能的时候的一些过程,以及自己的思路。其中也遇到一些问题,通过网上查找了相关一些资料,如有不对的地方或者待完善的地方,请多多指教。
思考
如果有多个数据源,需要同时执行DML的时候,此时如果出现异常的话,事务该如何保证数据源都能回滚?