Mybatis數(shù)據(jù)源切換的幾種方法小結(jié)
方案一:配置文件 + 硬編碼切換(基礎(chǔ)版)
你提到的第一種方式,是最基礎(chǔ)、最直觀的實現(xiàn)。它的核心流程是:
- 配置:在 application.yml 或 mybatis-config.xml 中定義多個數(shù)據(jù)源(如 master, slave1, slave2)。
- 持有:在代碼中通過一個工具類(比如使用 ThreadLocal)持有當(dāng)前線程要使用的數(shù)據(jù)源 key。
- 切換:在業(yè)務(wù)代碼中,手動調(diào)用工具類的方法(如 DataSourceContextHolder.setDataSource("slave1"))來切換。
| 維度 | 評價 |
|---|---|
| 優(yōu)點 | 簡單直接,容易理解,沒有黑盒。適合業(yè)務(wù)邏輯簡單、數(shù)據(jù)源切換點非常明確的場景。 |
| 缺點 | 切換邏輯和業(yè)務(wù)代碼耦合,侵入性強。如果忘記在方法結(jié)束時清除上下文,可能導(dǎo)致后續(xù)邏輯使用了錯誤的數(shù)據(jù)源,產(chǎn)生難以追蹤的 Bug。 |
方案二:AOP 切面編程(解耦版)
這是對方案一的優(yōu)化,也是目前最常用的實踐。它通過 Spring AOP 將“切換”這個動作從業(yè)務(wù)代碼中抽離出來。
核心邏輯是:定義一個注解(如 @DataSource("slave1")),然后編寫一個切面,攔截所有帶有該注解的方法,在方法執(zhí)行前解析注解并將數(shù)據(jù)源標(biāo)識設(shè)置到 ThreadLocal 中,方法執(zhí)行后在 @After 中清除標(biāo)識。
| 維度 | 評價 |
|---|---|
| 優(yōu)點 | 切換邏輯與業(yè)務(wù)解耦,代碼更干凈。只需在類或方法上加一個注解就能切換,可維護性高,是生產(chǎn)環(huán)境最推薦的實現(xiàn)方式。 |
| 缺點 | 需要編寫切面類和注解,有一定學(xué)習(xí)成本。對 AOP 的作用范圍(如 @Transactional 的優(yōu)先級)需要特別注意,避免事務(wù)開啟后再切換數(shù)據(jù)源導(dǎo)致切換失效。 |
方案三:繼承AbstractRoutingDataSource(動態(tài)路由版)
這是 Spring 提供的官方擴展點,也是實現(xiàn)方案一和方案二的底層基石。
AbstractRoutingDataSource 本身是一個數(shù)據(jù)源,它內(nèi)部管理著一個 Map<Object, Object> 來存放真實數(shù)據(jù)源,并根據(jù) determineCurrentLookupKey() 方法返回的 key 來決定路由到哪個真實數(shù)據(jù)源。我們只需要實現(xiàn)這個方法來返回我們通過 ThreadLocal 設(shè)置的 key 即可。
很多資料和第三方庫(包括 MyBatis-Plus 的 dynamic-datasource)的底層,本質(zhì)上都是對 AbstractRoutingDataSource 的封裝和增強。
方案四:使用第三方庫(成熟版)
你提到的 Druid(數(shù)據(jù)庫連接池)和 HikariCP(連接池),它們本身并不直接提供數(shù)據(jù)源切換功能,但它們是這個方案中不可或缺的“高性能連接池”組件。
真正用于動態(tài)切換數(shù)據(jù)源的明星第三方庫,是 MyBatis-Plus 生態(tài)下的 dynamic-datasource。
| 維度 | 評價 |
|---|---|
| 優(yōu)點 | 開箱即用,功能強大。支持?jǐn)?shù)據(jù)源分組、密碼解密、多主多從、敏感信息加密、集成 Seata 分布式事務(wù)等。只需引入依賴并在 application.yml 中配置,然后直接在方法上使用 @DS("slave1") 注解即可。 |
| 缺點 | 引入了一個外部依賴。如果項目沒有使用 MyBatis-Plus,需要額外集成。對于非常簡單的需求,可能顯得有點“重”。 |
?? 最終選擇指南
| 你的情況 | 推薦方案 |
|---|---|
| 項目簡單,切換點極少(1-2個),且未來不會擴展 | 方案一(硬編碼)即可。 |
| 標(biāo)準(zhǔn)企業(yè)級應(yīng)用,使用 Spring Boot + MyBatis | 方案二(自研 AOP + AbstractRoutingDataSource) 是主流選擇,平衡了靈活性與可控性。 |
| 已經(jīng)使用 MyBatis-Plus,或希望最大程度簡化配置 | 方案四(dynamic-datasource 插件) 是最高效的選擇。 |
| 有非常復(fù)雜的動態(tài)路由規(guī)則(如根據(jù) userId 哈希取模) | 方案三(繼承 AbstractRoutingDataSource) 是最靈活、最底層的方式,可以在 determineCurrentLookupKey() 中實現(xiàn)任意邏輯。 |
對于大多數(shù)項目,方案二(AOP + 注解 + AbstractRoutingDataSource) 和 方案四(MyBatis-Plus 的 dynamic-datasource) 是最值得考慮的。
另外補充一點,無論選擇哪種方案,都要注意:如果在 Spring 事務(wù)(@Transactional)中切換數(shù)據(jù)源,必須在事務(wù)開啟之前進行。因為事務(wù)管理器在開啟時就已經(jīng)確定了要使用的數(shù)據(jù)源,之后的切換將不會生效。如果需要在事務(wù)中切換數(shù)據(jù)源,可以考慮使用 @Transactional(propagation = Propagation.REQUIRES_NEW) 開啟一個新的事務(wù),或?qū)⑶袚Q邏輯放在一個沒有事務(wù)的方法中調(diào)用。
到此這篇關(guān)于Mybatis數(shù)據(jù)源切換的幾種方法小結(jié)的文章就介紹到這了,更多相關(guān)Mybatis數(shù)據(jù)源切換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于Mybatis-plus設(shè)置字段為空的正確寫法
這篇文章主要介紹了關(guān)于Mybatis-plus設(shè)置字段為空的正確寫法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
Java調(diào)用第三方http接口的常用方式總結(jié)
這篇文章主要介紹了Java調(diào)用第三方http接口的常用方式總結(jié),具有很好的參考價值,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
Java實現(xiàn)將對象轉(zhuǎn)換為二進制流再轉(zhuǎn)為Base64字符串
這篇文章主要為大家詳細介紹了如何使用Java實現(xiàn)將對象轉(zhuǎn)換為二進制流再轉(zhuǎn)為Base64字符串,本文提供了四種方法,大家可以根據(jù)需要進行選擇2025-12-12
基于Java開發(fā)實現(xiàn)ATM系統(tǒng)
這篇文章主要為大家詳細介紹了基于Java開發(fā)實現(xiàn)ATM系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08
java -jar設(shè)置添加啟動參數(shù)實現(xiàn)方法
這篇文章主要介紹了java -jar設(shè)置添加啟動參數(shù)實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02

