SpringBoot+mybatis-plus實現多數據源配置的詳細步驟
MyBatis-Plus 多數據源配置詳解
在日益復雜的業(yè)務場景中,單一數據源往往難以滿足微服務架構下的多元化需求,例如數據庫的讀寫分離、分庫分表、以及連接不同業(yè)務模塊的獨立數據庫等。MyBatis-Plus 作為一款廣受歡迎的持久層框架,通過其強大的擴展性,為開發(fā)者提供了靈活便捷的多數據源配置方案。
本文將詳細介紹兩種主流的 MyBatis-Plus 多數據源配置方式:一種是官方推薦且廣為使用的 dynamic-datasource-spring-boot-starter 插件,另一種是基于 AOP(面向切面編程)的手動配置方案,以幫助開發(fā)者根據項目需求做出最優(yōu)選擇。
推薦方案:使用dynamic-datasource-spring-boot-starter
dynamic-datasource-spring-boot-starter 是一個由 MyBatis-Plus 團隊成員開源的 Spring Boot 多數據源啟動器,它提供了豐富的功能和簡便的配置,是實現動態(tài)數據源切換的首選方案。
核心特性:
- 數據源分組: 適用于讀寫分離、一主多從等復雜場景。
- 多種切換方式: 支持注解、AOP以及編程方式的靈活切換。
- 動態(tài)數據源: 支持項目啟動后動態(tài)地增加或移除數據源。
- 組件集成: 無縫集成 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 注解是切換數據源最便捷的方式,可以作用于類或方法上。方法上的注解優(yōu)先級高于類上的注解。
@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. 編程方式(手動切換)
在某些復雜的業(yè)務場景下,需要在代碼中動態(tài)決定使用哪個數據源,此時可以使用 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();
// ... 創(chuàng)建訂單等操作,使用默認數據源
}
}
手動配置方案:基于 AOP 實現
對于希望擁有更高自由度或不愿引入額外依賴的開發(fā)者,可以采用自定義注解和 AOP 的方式手動實現動態(tài)數據源切換。其核心原理是利用 Spring 提供的 AbstractRoutingDataSource 類。
1. 添加 AOP 依賴
在 pom.xml 中確保已引入 AOP 相關依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2. 自定義數據源注解
創(chuàng)建一個注解,用于在需要切換數據源的方法上進行標識。
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String value();
}
3. 創(chuàng)建動態(tài)數據源上下文
使用 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
這是實現動態(tài)數據源的核心,通過重寫 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 切面
創(chuàng)建切面,攔截帶有 @DataSource 注解的方法,在方法執(zhí)行前后設置和清除數據源 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 |
|---|---|---|
| 易用性 | 高,開箱即用,配置簡單。 | 中,需要手動編寫較多代碼。 |
| 功能豐富度 | 高,支持分組、動態(tài)數據源、分布式事務等。 | 低,僅實現基礎的切換功能。 |
| 靈活性 | 高,支持多種切換方式。 | 高,完全自定義實現,可控性強。 |
| 依賴 | 引入額外 starter 依賴。 | 無需額外依賴,更為輕量。 |
選擇建議:
- 對于絕大多數項目,特別是追求開發(fā)效率和穩(wěn)定性的團隊,強烈推薦使用
dynamic-datasource-spring-boot-starter。 - 如果項目對依賴有嚴格控制,或需要實現高度定制化的數據源切換邏輯,可以選擇 手動配置 AOP 的方式。
注意事項
- 事務管理: 在多數據源環(huán)境下,需要特別注意事務的一致性。對于單個數據源內的事務,Spring 的
@Transactional依然有效。但對于跨多個數據源的分布式事務,則需要引入如 Seata 等分布式事務解決方案。 - AOP順序: 如果同時使用了
@Transactional和@DS注解,需要注意 AOP 的執(zhí)行順序,確保數據源切換在事務開啟之前執(zhí)行。
通過以上兩種方案的介紹,開發(fā)者可以根據自身項目的實際需求和團隊的技術棧,選擇最合適的方式來配置和管理 MyBatis-Plus 的多數據源,從而構建出更加健壯和可擴展的應用系統。
到此這篇關于SpringBoot+mybatis-plus實現多數據源配置的詳細步驟的文章就介紹到這了,更多相關SpringBoot mybatis-plus多數據源配置內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
認證授權中解決AuthenticationManager無法注入問題
這篇文章主要介紹了認證授權中解決AuthenticationManager無法注入問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-10-10
一文詳解如何從零構建Spring?Boot?Starter并實現整合
Spring Boot是一個開源的Java基礎框架,用于創(chuàng)建獨立、生產級的基于Spring框架的應用程序,這篇文章主要介紹了如何從零構建Spring?Boot?Starter并實現整合的相關資料,需要的朋友可以參考下2025-03-03
Eclipse中maven異常Updating Maven Project的統一解決方案
今天小編就為大家分享一篇關于Eclipse中maven異常Updating Maven Project的統一解決方案,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12

