Spring Boot + Druid 多数据源绑定
版本环境:Spring Boot 2.0.6
参考文档地址:
https://blog.csdn.net/cllaure/article/details/81509303
1. 项目结构
列举个几个比较重要的文件,其他的文件进行了省略
- analysis
- AnalysisApplication.java
- SpringUtil.java
- dao
- OperateLogMapper.java
- datasource
- DynamicDataSource.java
- DynamicDataSourceAspect.java
- DynamicDataSourceContextHolder.java
- DynamicDataSourceRegister.java
- TargetDataSource.java
- entity
- service
- AnalysisService.java
- utils
2. 关于启动类 AnalysisApplication
因为我想要的是在启动该项目时,不通过访问 url 的方式来激活某个接口,而是让程序自动来执行某个方法,所以需要在启动类中使用 SpringUtil.getApplicationContext()
来获取 Spring 上下文,从而将你需要的那个类注入进来,并执行该来的方法
1 | @SpringBootApplication |
3. 关于 SpringUtil
需要注意的是,此类需要放到启动类同包或者子包下才能被扫描,否则失效。
1 | @Component |
4. 多数据源连接初始化
首先创建一个 datasource 的文件夹,该文件夹下需要的文件有:
- DynamicDataSource.java
- DynamicDataSourceAspect.java
- DynamicDataSourceContextHolder.java
- DynamicDataSourceRegister.java
- TargetDataSource.java
如果是想通过注解的方法来切换数据源,那么需要用到 DynamicDataSourceAspect.java
和 TargetDataSource.java
,反之如果你的数据源连接特别多,要通过传参来切换数据源,那么就不需要这两个文件。
下面我会按照多数据源连接为例,改写文档上的代码。
4.1 DynamicDataSource.java
这个文件的目的是覆写 determineCurrentLookupKey()
方法,返回的值是保存在 DynamicDataSourceContextHolder
类中当前数据库连接
1 | public class DynamicDataSource extends AbstractRoutingDataSource { |
4.2 DynamicDataSourceContextHolder.java
该文件是用来切换数据源,通过 setDataSourceType(String dataSourceType)
方法来切换到指定的数据库连接,其中 dataSourceType
其实是在初始化数据库连接时的别名。
dataSourceIds
里保存了所有数据库连接的别名。
1 | public class DynamicDataSourceContextHolder { |
4.3 DynamicDataSourceRegister.java
该文件用来初始化数据源连接,并注入到 Bean 中。
Spring 启动前,会自动执行 setEnvironment(Environment env)
方法,在这个方法体通过读取配置文件,来初始化数据库连接。由于我们需要通过别名来切换数据库连接,所以如果在库名唯一的情况下,我们可以通过数据库名来作为别名。
1 | /** |
4.4 DynamicDataSourceAspect.java
这个文件主要用来编写在引用了注解的方法执行前后所需要做的操作。
1 | /** |
4.5 TargetDataSource.java
注解文件
1 | // 在方法上使用,用于指定使用哪个数据源 |
5. 方法实现
如果是通过注解实现,可以在此文件中的方法或者dao层中的方法上使用注解,并通过对 name
进行赋值来切换数据库,如果没有值的话使用的是默认数据库连接。
1 | @Component |
6. 关于 MyBatis.xml
使用 MyBatis 来编写 sql 语句时,将表名通过变量传递。此时如果用 #{0}
,会报错,因为 #
会把里面的参数自动加上单引号然后拼接到字符串上,如果是对于类似 where name = '张三'
是没有问题的,但是对于 select * from 'tableName'
是有问题的。
有两个解决方法,一个是将需要传递的参数打包成 HashMap,在赋值的时候使用 select * from ${_key}
, 这样就可以动态赋值了。第二个方法是传递N个参数,使用 select * from ${param1}
来进行赋值。