news 2026/4/29 10:11:44

Spring Boot 3.0动态多数据源切换实战教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring Boot 3.0动态多数据源切换实战教程

在现代企业级应用中,数据源切换是应对读写分离、多租户架构或分库分表等场景的常见需求。本教程将详细介绍如何在 Spring Boot 3.0 中,通过整合dynamic-datasource-spring-boot3-starter这一成熟的开源方案,以最小的代码量实现优雅、高效的多数据源动态切换。

一、为什么选择 dynamic-datasource-spring-boot3-starter

虽然 Spring 提供了AbstractRoutingDataSource作为底层支持,但手动实现一套完整的动态数据源切换机制(包括 AOP 切面、ThreadLocal 上下文管理等)较为繁琐。dynamic-datasource项目正是为了解决这一痛点而生,它基于 Spring Boot 的自动装配机制,提供了一套开箱即用的解决方案。

核心优势

  • 零配置启动:通过简单的application.yml配置即可定义多个数据源。
  • 注解驱动:使用@DS注解即可在 Service 层或 Mapper 层轻松切换数据源。
  • 功能丰富:原生支持读写分离、多数据源组、SpEL 表达式等高级特性。
  • Spring Boot 3 原生支持dynamic-datasource-spring-boot3-starter专门为 Spring Boot 3.x 设计,完美兼容 Jakarta EE 规范。
二、项目依赖与配置

1、添加 Maven 依赖
在项目的pom.xml文件中,添加dynamic-datasource-spring-boot3-starter依赖。请确保你的 Spring Boot 版本为 3.x。

<dependencies> <!-- Spring Boot Web Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 动态数据源 Starter for Spring Boot 3 --> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <version>4.3.0</version> <!-- 请使用最新稳定版本 --> </dependency> <!-- 数据库驱动,以 MySQL 为例 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- MyBatis-Plus Starter (可选,用于简化数据访问层) --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>3.5.5</version> </dependency> </dependencies>

2、配置多数据源
src/main/resources/application.yml中进行配置。dynamic前缀下的primary属性用于指定默认数据源,datasource下则定义具体的数据源连接信息。

spring: datasource: dynamic: # 设置默认数据源,未指定 @DS 注解时将使用此数据源 primary: master # 开启 SQL 日志打印,方便调试 p6spy: true datasource: # 主库配置,用于写操作 master: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db_master?useSSL=false&serverTimezone=UTC username: root password: your_password # 从库配置,用于读操作 slave: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db_slave?useSSL=false&serverTimezone=UTC username: root password: your_password
三、核心代码实现

1、定义数据实体与 Mapper
首先,创建一个简单的用户实体类User

import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; @Data @TableName("user") public class User { @TableId(type = IdType.AUTO) private Long id; private String username; private String email; }

接着,创建对应的 MyBatis-Plus Mapper 接口。

import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; @Mapper public interface UserMapper extends BaseMapper<User> { // 继承 BaseMapper 后,已拥有基础的 CRUD 方法 }

2、在 Service 层使用 @DS 注解
@DS注解是实现数据源切换的关键。它可以标注在类或方法上,方法上的注解优先级更高。

import com.baomidou.dynamic.datasource.annotation.DS; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service public class UserService { private final UserMapper userMapper; public UserService(UserMapper userMapper) { this.userMapper = userMapper; } /** * 写操作,使用默认的 master 数据源。 * 由于 application.yml 中 primary 设置为 master,因此此处可不加 @DS 注解。 */ @Transactional public void addUser(User user) { userMapper.insert(user); } /** * 读操作,通过 @DS("slave") 明确指定使用 slave 数据源。 * 这实现了读写分离,减轻主库压力。 */ @DS("slave") public List<User> getAllUsers() { return userMapper.selectList(null); } /** * 也可以在类级别上使用 @DS 注解, * 那么该类下所有方法默认都会使用指定的数据源。 */ }

3、编写 Controller 进行测试
创建一个简单的 REST Controller 来暴露接口,方便测试。

import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/users") public class UserController { private final UserService userService; public UserController(UserService userService) { this.userService = userService; } @PostMapping public void createUser(@RequestBody User user) { userService.addUser(user); } @GetMapping public List<User> listUsers() { // 调用此方法将查询从库 return userService.getAllUsers(); } }
四、高级特性与最佳实践

1、读写分离与负载均衡
dynamic-datasource支持更复杂的读写分离配置。你可以定义一个数据源组,其中包含一个主库和多个从库。当进行读操作时,它会自动在从库间进行负载均衡(默认轮询)。

spring: datasource: dynamic: primary: mydb # 默认数据源组 datasource: mydb: # 定义一个名为 mydb 的组 master: # 组内的主库 url: jdbc:mysql://localhost:3306/db_master... username: root password: password slave1: # 组内的从库1 url: jdbc:mysql://localhost:3306/db_slave1... username: root password: password slave2: # 组内的从库2 url: jdbc:mysql://localhost:3306/db_slave2... username: root password: password

使用方式不变,@DS("mydb")进行写操作时会自动路由到master,进行读操作时则会在slave1slave2之间负载均衡。

2、多数据源事务管理
这是一个需要特别注意的要点。@Transactional注解是基于数据源绑定的。当一个方法被@DS@Transactional同时修饰时,事务将作用于@DS指定的数据源。

重要提醒:应避免在单个@Transactional方法内跨越多个数据源进行操作。Spring 的声明式事务管理器无法保证跨库操作的原子性。如果需要处理跨库业务,应考虑使用分布式事务框架(如 Seata),或将业务逻辑拆分为多个独立的、各自管理单一数据源的事务方法。

3、运行时动态管理数据源
对于多租户 SaaS 应用,可能需要根据租户 ID 动态创建和销毁数据源。dynamic-datasource提供了DynamicDataSourceService接口来实现这一功能。

import com.baomidou.dynamic.datasource.DynamicDataSourceService; import com.baomidou.dynamic.datasource.creator.DataSourceProperty; import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator; import org.springframework.stereotype.Service; @Service public class TenantDataSourceService { private final DynamicDataSourceService dynamicDataSourceService; private final DefaultDataSourceCreator dataSourceCreator; public TenantDataSourceService(DynamicDataSourceService dynamicDataSourceService, DefaultDataSourceCreator dataSourceCreator) { this.dynamicDataSourceService = dynamicDataSourceService; this.dataSourceCreator = dataSourceCreator; } // 为指定租户添加数据源 public void addTenantDataSource(String tenantId, String jdbcUrl, String username, String password) { DataSourceProperty property = new DataSourceProperty(); property.setPoolName(tenantId); // 连接池名称 property.setUrl(jdbcUrl); property.setUsername(username); property.setPassword(password); property.setDriverClassName("com.mysql.cj.jdbc.Driver"); // 创建并添加数据源 dynamicDataSourceService.addDataSource(dataSourceCreator.createDataSource(property)); } // 移除指定租户的数据源 public void removeTenantDataSource(String tenantId) { dynamicDataSourceService.removeDataSource(tenantId); } }

通过以上步骤,你可以在 Spring Boot 3.0 项目中快速、稳定地实现多数据源动态切换,满足各种复杂的业务场景需求。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 18:51:12

QMCDecode:终极指南!如何轻松将QQ音乐加密格式转换为通用音频

QMCDecode&#xff1a;终极指南&#xff01;如何轻松将QQ音乐加密格式转换为通用音频 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac&#xff0c;qmc0,qmc3转mp3, mflac,mflac0等转flac)&#xff0c;仅支持macOS&#xff0c;可自动识别到QQ音乐下载目录…

作者头像 李华
网站建设 2026/4/14 23:27:08

**图算法新视角:用Python实现复杂网络中的最短路径优化与可视化**在现代软件开发中,图算法早已不是“理论课”的专属内容

8图算法新视角&#xff1a;用Python实现复杂网络中的最短路径优化与可视化* 在现代软件开发中&#xff0c;图算法早已不是“理论课”的专属内容。它深入到推荐系统、社交网络分析、交通路径规划甚至金融风控等多个核心场景。今天&#xff0c;我们不讲经典dijkstra或Floyd-Warsh…

作者头像 李华
网站建设 2026/4/14 23:26:04

ClaudeSkills解决了什么问题?还有哪些问题没解决?

Claude Skills 解决了什么问题&#xff1f;还有哪些问题没解决&#xff1f;Anthropic 的 Claude Skills 是优秀的工程方案&#xff0c;但它解决的是"单一超级 Agent"路线上的模块化补救。本文从工程师视角分析 Skills 的边界&#xff0c;并探讨"原生多 Agent 矩…

作者头像 李华
网站建设 2026/4/16 7:36:12

微信小程序考试系统(30060)

有需要的同学&#xff0c;源代码和配套文档领取&#xff0c;加文章最下方的名片哦 一、项目演示 项目演示视频 二、资料介绍 完整源代码&#xff08;前后端源代码SQL脚本&#xff09;配套文档&#xff08;LWPPT开题报告/任务书&#xff09;远程调试控屏包运行一键启动项目&…

作者头像 李华
网站建设 2026/4/16 18:50:54

MasterPDF多功能PDF编辑软件:解决PDF编辑与水印添加等常见问题

在日常办公中&#xff0c;你是否遇到过这样的困扰&#xff1a;收到一份PDF合同&#xff0c;发现有个错别字却无法修改&#xff1b;需要给多页PDF文档添加“机密”水印&#xff0c;却只能一页页截图粘贴&#xff1b;或者想合并多个PDF文件&#xff0c;却找不到一个简单免费的工具…

作者头像 李华