spring boot 动态数据源切换
所谓动态数据源是指运行时动态的改变数据源,spring boot 默认可以配置一个数据源,要同时支持 mysql 和 oracle 都不太容易,而如果能动态切换数据源,自然也能同时存在数个数据源,且可以随意切换,本文是之前几篇博客的升华,即使用 aop 技术实现动态的修改运行时数据源。
如果你懒得看具体怎么实现,直接拿我的成果吧,在 pom.xml 里添加依赖:
如果遇到错误:The bean ‘dataSource’ could not be registered. A bean with that name has already been defined in class path resource,直接在 application.properties 里新增:spring.main.allow-bean-definition-overriding=true 即可,另外,你还需要配置你额外的数据库,比如:
dynamic.datasource.name=data2
dynamic.datasource.data2.url=jdbc:mysql://localhost:3506/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
dynamic.datasource.data2.username=test
dynamic.datasource.data2.password=test
dynamic.datasource.data2.driver-class-name=com.mysql.cj.jdbc.Driver
这里,name 后面是 list,你可以写 data2,也可以写 data2, data3 等,多个的时候用逗号分割,下面的 dynamic.datasource.data2.xxx 是该数据库的配置信息,此处的 data2 也可以是你自定义的任意值。 然后在 mapper 文件里添加注解,比如:
|
|
其中,类上的注解是针对这个类里所有方法的,而方法上的注解可以覆盖类上的注解,如果配置如上,除了 selectByPrimaryKey 将使用 test 这个数据库外,其余都使用 data2,如果你没有配置 test 这个数据库将使用你默认的数据库。 毫无疑问,这个解决方案完美的兼容已有的代码,且通过 aop 技术实现,没有耦合,如果你删除 pom.xml 里的依赖,顶多只是 application.properties 里显示警告而已,对已有系统侵入最小,下面是具体的实现。
- 首先,application.properties 里的配置是动态的,即 dynamic.datasource.data2.url 等这里的 data2 你可以随意写,但是后面却只能跟 password 等,这个的具体实现请参考:深入理解 spring boot 自定义属性 的最后部分。
- 关于如何 使用 idea 打包并上传 jar 包到 maven 中央仓库请参考:IDEA 打包并上传 jar 包 到 maven 中央仓库。
其实,spring boot 提供了动态切换数据源的方法,即 AbstractRoutingDataSource 这个类,它继承自 AbstractDataSource,也是个抽象类,你必须得实现 determineCurrentLookupKey 这个方法,而这个方法的作用就是:返回你所要使用的数据源的 key 值。比如:
然后你需要将数据库信息注册进去,之后在执行 sql 语句前,会调用这里的 determineCurrentLookupKey,最终调用:DynamicDataSourceContextHolder.getDataSourceType(); 而 DynamicDataSourceContextHolder 源码如下:
|
|
现在,大致应该明白,当你手动把数据库配置信息注册到 spring 后,在执行 sql 前,会调用 这里的 DynamicDataSourceContextHolder.getDataSourceType(); 以决定连接那个数据库,而 这个方法的值其实是 setDataSourceType 这个方法设置的,setDataSourceType 这个方法 和 clearDataSourceType 这个方法则是开放给 aop 层调用的,aop 层的代码如下:
|
|
以上代码,先判断方法本身是否含有 @DataSource 注解,如果没有则查看类是否有,如果也没有则啥也不执行,如果有,则会在方法执行前调用 setDataSourceType, 传入的参数就是 @DataSource(name=“xxx”) 里的 xxx,在方法执行结束,则调用 clearDataSourceType 方法,重置使用的数据库信息,以免影响别的 sql 执行。 完整的代码请查看:https://github.com/ijustyce/dynamic-data-source-spring-boot-starter