Spring Boot 3.4.0 結合 Mybatis-plus 實現(xiàn)動態(tài)數(shù)據(jù)源的完整方案
前言
在實際企業(yè)級應用開發(fā)中,多數(shù)據(jù)源的需求非常常見。本文將詳細介紹如何在 Spring Boot 3.4.0 項目中結合 Mybatis-plus 實現(xiàn)動態(tài)數(shù)據(jù)源切換功能。
一、環(huán)境準備
首先確保你的開發(fā)環(huán)境滿足以下要求:
- JDK 17+
- Spring Boot 3.4.0
- Mybatis-plus 3.5.3.1+
- Maven 3.6.3+
二、項目配置
1. 添加依賴
在 pom.xml
中添加以下依賴:
<dependencies> <!-- Spring Boot Starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency> <!-- 數(shù)據(jù)庫驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- 其他工具 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>
2. 配置文件
在 application.yml
中配置多個數(shù)據(jù)源:
spring: datasource: master: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/master_db?useSSL=false&serverTimezone=UTC username: root password: 123456 slave1: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/slave1_db?useSSL=false&serverTimezone=UTC username: root password: 123456 slave2: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/slave2_db?useSSL=false&serverTimezone=UTC username: root password: 123456
三、實現(xiàn)動態(tài)數(shù)據(jù)源
1. 數(shù)據(jù)源枚舉
public enum DataSourceType { MASTER("master"), SLAVE1("slave1"), SLAVE2("slave2"); private final String name; DataSourceType(String name) { this.name = name; } public String getName() { return name; } }
2. 動態(tài)數(shù)據(jù)源上下文
public class DynamicDataSourceContextHolder { private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDataSourceType(String dataSourceType) { CONTEXT_HOLDER.set(dataSourceType); } public static String getDataSourceType() { return CONTEXT_HOLDER.get(); } public static void clearDataSourceType() { CONTEXT_HOLDER.remove(); } }
3. 動態(tài)數(shù)據(jù)源配置
@Configuration @MapperScan(basePackages = "com.example.mapper") public class DynamicDataSourceConfig { @Bean @ConfigurationProperties("spring.datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties("spring.datasource.slave1") public DataSource slave1DataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties("spring.datasource.slave2") public DataSource slave2DataSource() { return DataSourceBuilder.create().build(); } @Bean public DataSource dynamicDataSource() { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceType.MASTER.getName(), masterDataSource()); targetDataSources.put(DataSourceType.SLAVE1.getName(), slave1DataSource()); targetDataSources.put(DataSourceType.SLAVE2.getName(), slave2DataSource()); DynamicDataSource dynamicDataSource = new DynamicDataSource(); dynamicDataSource.setTargetDataSources(targetDataSources); dynamicDataSource.setDefaultTargetDataSource(masterDataSource()); return dynamicDataSource; } @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
4. 動態(tài)數(shù)據(jù)源實現(xiàn)
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.getDataSourceType(); } }
5. 自定義注解
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { DataSourceType value() default DataSourceType.MASTER; }
6. AOP 切面實現(xiàn)
@Aspect @Component @Order(-1) @Slf4j public class DataSourceAspect { @Pointcut("@annotation(com.example.annotation.DataSource)" + "|| @within(com.example.annotation.DataSource)") public void dsPointCut() { } @Around("dsPointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { DataSource dataSource = getDataSource(point); if (dataSource != null) { DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().getName()); } try { return point.proceed(); } finally { DynamicDataSourceContextHolder.clearDataSourceType(); } } private DataSource getDataSource(ProceedingJoinPoint point) { MethodSignature signature = (MethodSignature) point.getSignature(); DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); if (dataSource != null) { return dataSource; } return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); } }
四、使用示例
1. Service 層使用
@Service public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override @DataSource(DataSourceType.MASTER) public User getMasterUser(Long id) { return userMapper.selectById(id); } @Override @DataSource(DataSourceType.SLAVE1) public User getSlave1User(Long id) { return userMapper.selectById(id); } @Override @DataSource(DataSourceType.SLAVE2) public User getSlave2User(Long id) { return userMapper.selectById(id); } }
2. Controller 層調(diào)用
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping("/master/{id}") public User master(@PathVariable Long id) { return userService.getMasterUser(id); } @GetMapping("/slave1/{id}") public User slave1(@PathVariable Long id) { return userService.getSlave1User(id); } @GetMapping("/slave2/{id}") public User slave2(@PathVariable Long id) { return userService.getSlave2User(id); } }
五、注意事項
- 事務管理:動態(tài)數(shù)據(jù)源切換與事務管理需要特別注意,建議在事務方法中不要切換數(shù)據(jù)源
- 連接池配置:可以為每個數(shù)據(jù)源單獨配置連接池參數(shù)
- 性能考慮:頻繁切換數(shù)據(jù)源可能會影響性能,應根據(jù)實際需求合理設計
- 異常處理:做好數(shù)據(jù)源切換失敗時的異常處理
六、總結
本文詳細介紹了在 Spring Boot 3.4.0 項目中結合 Mybatis-plus 實現(xiàn)動態(tài)數(shù)據(jù)源切換的完整方案。通過自定義注解和AOP切面,我們可以優(yōu)雅地實現(xiàn)方法級別的數(shù)據(jù)源切換,滿足多數(shù)據(jù)源場景下的各種需求。
到此這篇關于Spring Boot 3.4.0 結合 Mybatis-plus 實現(xiàn)動態(tài)數(shù)據(jù)源的完整方案的文章就介紹到這了,更多相關Spring Boot Mybatis-plus動態(tài)數(shù)據(jù)源內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
- SpringBoot整合Mybatis-Plus+Druid實現(xiàn)多數(shù)據(jù)源配置功能
- Spring Boot + Mybatis-Plus實現(xiàn)多數(shù)據(jù)源的方法
- 全網(wǎng)最新springboot整合mybatis-plus的過程
- 5分鐘快速搭建SpringBoot3?+?MyBatis-Plus工程/項目的實現(xiàn)示例
- Spring Boot 中整合 MyBatis-Plus詳細步驟(最新推薦)
- 淺談Spring Boot、MyBatis、MyBatis-Plus 依賴版本對應關系
- Springboot整合mybatis-plus使用pageHelper進行分頁(使用步驟)
相關文章
springboot整合springsecurity與mybatis-plus的簡單實現(xiàn)
Spring Security基于Spring開發(fā),項目中如果使用Spring作為基礎,配合Spring Security做權限更加方便,而Shiro需要和Spring進行整合開發(fā)。因此作為spring全家桶中的Spring Security在java領域很常用2021-10-10spring boot springjpa 支持多個數(shù)據(jù)源的實例代碼
這篇文章主要介紹了spring boot springjpa 支持多個數(shù)據(jù)源的實例代碼,需要的朋友可以參考下2018-04-04Spring Cloud Gateway 記錄請求應答數(shù)據(jù)日志操作
這篇文章主要介紹了Spring Cloud Gateway 記錄請求應答數(shù)據(jù)日志操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12MybatisPlus?LambdaQueryWrapper使用int默認值的坑及解決
這篇文章主要介紹了MybatisPlus?LambdaQueryWrapper使用int默認值的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。2022-01-01SpringBoot FailureAnalyzer實例使用教程
FailureAnalyzer是一種在啟動時攔截exception并將其轉換為human-readable消息的好方法,包含在故障分析中。SpringBoot為application context相關的exceptions,JSR-303驗證等提供了這樣的分析器,實際上很容易創(chuàng)建自己的2022-12-12Springboot中MyBatisplus使用IPage和Page分頁的實例代碼
這篇文章主要介紹了Springboot中MyBatisplus使用IPage和Page分頁,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12