SpringBoot+mybatis-plus实现多数据源配置的详细步骤
作者:冰糖心书房
MyBatis-Plus 多数据源配置详解
在日益复杂的业务场景中,单一数据源往往难以满足微服务架构下的多元化需求,例如数据库的读写分离、分库分表、以及连接不同业务模块的独立数据库等。MyBatis-Plus 作为一款广受欢迎的持久层框架,通过其强大的扩展性,为开发者提供了灵活便捷的多数据源配置方案。
本文将详细介绍两种主流的 MyBatis-Plus 多数据源配置方式:一种是官方推荐且广为使用的 dynamic-datasource-spring-boot-starter
插件,另一种是基于 AOP(面向切面编程)的手动配置方案,以帮助开发者根据项目需求做出最优选择。
推荐方案:使用dynamic-datasource-spring-boot-starter
dynamic-datasource-spring-boot-starter
是一个由 MyBatis-Plus 团队成员开源的 Spring Boot 多数据源启动器,它提供了丰富的功能和简便的配置,是实现动态数据源切换的首选方案。
核心特性:
- 数据源分组: 适用于读写分离、一主多从等复杂场景。
- 多种切换方式: 支持注解、AOP以及编程方式的灵活切换。
- 动态数据源: 支持项目启动后动态地增加或移除数据源。
- 组件集成: 无缝集成 MyBatis-Plus、Quartz、ShardingSphere 等多种组件。
- 分布式事务: 提供了基于 Seata 的分布式事务解决方案。
1. 引入依赖
根据您的 Spring Boot 版本,在 pom.xml
文件中引入相应的依赖:
Spring Boot 2.x:
<dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.5.2</version> <!-- 请使用最新版本 --> </dependency>
Spring Boot 3.x:
<dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <version>4.2.0</version> <!-- 请使用最新版本 --> </dependency>
2. 配置文件application.yml
在配置文件中定义多个数据源,并指定主数据源。
spring: datasource: dynamic: primary: master # 设置默认的数据源 strict: false # 设置为true时,未匹配到数据源会报错,设置为false则使用默认数据源 datasource: master: url: jdbc:mysql://localhost:3306/db_master?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: password123 driver-class-name: com.mysql.cj.jdbc.Driver slave_1: url: jdbc:mysql://localhost:3306/db_slave1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: password123 driver-class-name: com.mysql.cj.jdbc.Driver
3. 数据源切换方式
a. 注解方式(@DS)
@DS
注解是切换数据源最便捷的方式,可以作用于类或方法上。方法上的注解优先级高于类上的注解。
@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { @DS("slave_1") // 指定使用slave_1数据源 @Override public List<User> getSlaveUsers() { return this.list(); } @Override public List<User> getMasterUsers() { // 未使用@DS注解,将使用默认的master数据源 return this.list(); } }
b. 编程方式(手动切换)
在某些复杂的业务场景下,需要在代码中动态决定使用哪个数据源,此时可以使用 DynamicDataSourceContextHolder
进行手动切换。
@Service public class OrderServiceImpl implements OrderService { @Autowired private ProductService productService; @Autowired private StockService stockService; public void createOrder(String productId, int amount) { // 查询商品信息,切换到slave数据源 DynamicDataSourceContextHolder.push("slave_1"); Product product = productService.getById(productId); DynamicDataSourceContextHolder.clear(); // 每次使用后必须清空 // 扣减库存,切换到master数据源 DynamicDataSourceContextHolder.push("master"); stockService.deduct(productId, amount); DynamicDataSourceContextHolder.clear(); // ... 创建订单等操作,使用默认数据源 } }
手动配置方案:基于 AOP 实现
对于希望拥有更高自由度或不愿引入额外依赖的开发者,可以采用自定义注解和 AOP 的方式手动实现动态数据源切换。其核心原理是利用 Spring 提供的 AbstractRoutingDataSource
类。
1. 添加 AOP 依赖
在 pom.xml
中确保已引入 AOP 相关依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2. 自定义数据源注解
创建一个注解,用于在需要切换数据源的方法上进行标识。
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { String value(); }
3. 创建动态数据源上下文
使用 ThreadLocal
存储当前线程需要使用的数据源名称,以确保线程安全。
public class DynamicDataSourceContextHolder { private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDataSourceKey(String key) { CONTEXT_HOLDER.set(key); } public static String getDataSourceKey() { return CONTEXT_HOLDER.get(); } public static void clearDataSourceKey() { CONTEXT_HOLDER.remove(); } }
4. 实现AbstractRoutingDataSource
这是实现动态数据源的核心,通过重写 determineCurrentLookupKey
方法,从 DynamicDataSourceContextHolder
中获取当前数据源的 key。
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.getDataSourceKey(); } }
5. 配置数据源
通过 Java Config 的方式配置多个数据源,并将它们注入到 DynamicDataSource
中。
@Configuration public class DataSourceConfig { @Bean @ConfigurationProperties("spring.datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties("spring.datasource.slave") public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); } @Bean @Primary public DynamicDataSource dataSource(DataSource masterDataSource, DataSource slaveDataSource) { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put("master", masterDataSource); targetDataSources.put("slave", slaveDataSource); DynamicDataSource dataSource = new DynamicDataSource(); dataSource.setTargetDataSources(targetDataSources); dataSource.setDefaultTargetDataSource(masterDataSource); return dataSource; } }
并在 application.yml
中配置相应的数据源信息:
spring: datasource: master: url: jdbc:mysql://localhost:3306/db_master... # ... slave: url: jdbc:mysql://localhost:3306/db_slave1... # ...
6. 编写 AOP 切面
创建切面,拦截带有 @DataSource
注解的方法,在方法执行前后设置和清除数据源 key。
@Aspect @Component public class DataSourceAspect { @Pointcut("@annotation(com.example.annotation.DataSource)") public void dataSourcePointCut() { } @Around("dataSourcePointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); DataSource dataSource = method.getAnnotation(DataSource.class); if (dataSource != null) { DynamicDataSourceContextHolder.setDataSourceKey(dataSource.value()); } try { return point.proceed(); } finally { DynamicDataSourceContextHolder.clearDataSourceKey(); } } }
方案对比与选择
特性 | dynamic-datasource-spring-boot-starter | 手动配置 AOP |
---|---|---|
易用性 | 高,开箱即用,配置简单。 | 中,需要手动编写较多代码。 |
功能丰富度 | 高,支持分组、动态数据源、分布式事务等。 | 低,仅实现基础的切换功能。 |
灵活性 | 高,支持多种切换方式。 | 高,完全自定义实现,可控性强。 |
依赖 | 引入额外 starter 依赖。 | 无需额外依赖,更为轻量。 |
选择建议:
- 对于绝大多数项目,特别是追求开发效率和稳定性的团队,强烈推荐使用
dynamic-datasource-spring-boot-starter
。 - 如果项目对依赖有严格控制,或需要实现高度定制化的数据源切换逻辑,可以选择 手动配置 AOP 的方式。
注意事项
- 事务管理: 在多数据源环境下,需要特别注意事务的一致性。对于单个数据源内的事务,Spring 的
@Transactional
依然有效。但对于跨多个数据源的分布式事务,则需要引入如 Seata 等分布式事务解决方案。 - AOP顺序: 如果同时使用了
@Transactional
和@DS
注解,需要注意 AOP 的执行顺序,确保数据源切换在事务开启之前执行。
通过以上两种方案的介绍,开发者可以根据自身项目的实际需求和团队的技术栈,选择最合适的方式来配置和管理 MyBatis-Plus 的多数据源,从而构建出更加健壮和可扩展的应用系统。
到此这篇关于SpringBoot+mybatis-plus实现多数据源配置的详细步骤的文章就介绍到这了,更多相关SpringBoot mybatis-plus多数据源配置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!