在实际开发中,多数据源几乎是绕不开的需求——比如业务库与日志库分离、读写分离,或者对接外部系统。虽然Spring Boot本身提供了配置多个DataSource的方式,但手动切换较为繁琐,尤其是在运行时需要动态决定使用哪个库的场景下。此时,借助dynamic-datasource这个库会方便得多,它基于Spring的AbstractRoutingDataSource进行了封装,配合注解即可实现优雅的多数据源切换。
简单来说,动态多数据源配置就是让应用在运行时能够“看情况”选择连接哪个数据库。基本思路是先定义好几个数据源的连接信息,然后通过一个管理类动态决定当前使用哪个数据源,最后在业务代码中通过注解或API来标记切换逻辑。dynamic-datasource正是一个开源的Java库,它将上述步骤简化为“配置+注解”的模式。
使用步骤非常清晰:先在pom.xml中引入依赖,然后在配置文件中声明每个数据源的连接参数,再指定一个默认数据源(比如primary: system)。之后在Mapper或者Service方法上打上@DS注解,就能实现数据源的切换。下面通过一个实际案例来走一遍完整流程。
1、创建数据库(表)
首先在MySQL中创建两个库,一个命名为system,一个命名为log,并分别在其中创建对应的表。具体表结构可根据实际业务自行定义。

2、POM依赖
在项目中添加Mybatis和dynamic-datasource的starter依赖,此处使用mybatis-spring-boot-starter 2.2.2和dynamic-datasource-spring-boot-starter 3.5.1。
org.mybatis.spring.boot mybatis-spring-boot-starter 2.2.2 com.baomidou dynamic-datasource-spring-boot-starter 3.5.1
3、配置yaml
在application.yml中配置两个数据源,分别命名为system和log。注意设置spring.datasource.dynamic.primary: system,这样未指定数据源的地方会默认走system库。同时建议开启Hikari连接池参数,下面给出常见配置。
spring:
application:
name: quartz
datasource:
dynamic:
primary: system
strict: false
datasource:
system:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3307/system?useUnicode=true&useSSL=false&zeroDateTimeBeha vior=convertToNull&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password: lhzlx
log:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3307/log?useUnicode=true&useSSL=false&zeroDateTimeBeha vior=convertToNull&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Shanghai
username: root
password: lhzlx
type: com.zaxxer.hikari.HikariDataSource
hikari:
maximum-pool-size: 10
minimum-idle: 2
connection-timeout: 60000
idle-timeout: 600000
max-lifetime: 640000
connection-test-query: SELECT 1
mybatis:
mapper-locations: classpath*:mappers/*.xml
type-aliases-package: com.lhz.demo.model.entity
configuration.database-id: mysql
configuration.map-underscore-to-camel-case: true
4、Mapper接口
在mapper包下创建两个接口,一个对应system库,一个对应log库。直接在SysMapper接口上使用@DS("log"),表示该接口下的所有操作都走log数据源;LogMapper不加注解,默认走system。当然,你也可以将注解加到具体方法上,这样更加灵活。
LogMapper:
@Mapper
public interface LogMapper {
List selectAll();
}
SysMapper:
@Mapper
@DS("log")
public interface SysMapper {
List selectAll();
}
5、Mapper XML
在resources/mappers目录下创建对应的XML文件,编写标准的select语句即可。
LogMapper.xml:
SystemMapper.xml:
6、Service
在Service层注入两个Mapper,然后分别编写两个方法。其中一个方法不加@DS注解,默认使用system数据源;另一个方法加上@DS("log"),显式指定使用log库。
@Service
public class TestService {
@Resource
private SysMapper sysMapper;
@Resource
private LogMapper logMapper;
/**
* 不指定数据源,默认使用system数据源
*/
public Object sys() {
return sysMapper.selectAll();
}
/**
* 指定使用log数据源
*/
@DS("log")
public Object log() {
return logMapper.selectAll();
}
}
7、Controller
编写两个接口,分别调用Service中的两个方法,用于验证切换效果。
@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {
@Resource
private TestService testService;
@GetMapping("/sys")
public Object sys() {
return testService.sys();
}
@GetMapping("/log")
public Object log() {
return testService.log();
}
}
8、测试
启动项目后,分别访问https://localhost:9090/test/sys和https://localhost:9090/test/log。如果两个接口都能正常返回各自数据库里的数据,说明多数据源配置已成功完成。


整个过程下来,你会发现dynamic-datasource最大的好处就是省去了手动编写RoutingDataSource的繁琐操作,只需一个注解即可轻松搞定数据源切换。如果你的项目里也有多个数据库需要操作,不妨试试这个方案。
