springboot使用dynamic做多數(shù)據(jù)源配置全過程
最近項目需求,需要用到多數(shù)據(jù)源配置,經(jīng)過一番學(xué)習(xí)完成需求功能開發(fā),本文介紹一下我用到的dynamic做動態(tài)數(shù)據(jù)源配置。
1. 依賴導(dǎo)入
這里用到dynamic依賴,和對應(yīng)的數(shù)據(jù)源(mysql,oracle等)依賴。以下是dynamic依賴:
<dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>3.5.0</version> </dependency>
2.yml配置
yml配置主要是將多個數(shù)據(jù)源分別配置,并指定默認(rèn)數(shù)據(jù)源,具體yml配置參考如下:
spring:
datasource:
dynamic:
primary: kingbase # 設(shè)置主庫為kingbase
strict: false # 嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)false,當(dāng)為true時,未匹配到指定數(shù)據(jù)源時拋異常,false未匹配到指定數(shù)據(jù)源會使用默認(rèn)數(shù)據(jù)源
datasource:
kingbase: # 這的kingbase是自定義的數(shù)據(jù)源名稱,不是指數(shù)據(jù)庫的類型
url: jdbc:kingbase8://${DATABASE_HOST:127.0.0.1}:${DATABASE_PORT:54323}/${DATABASE_DBNAME:kingbase}?serverTimezone=GTM%2B8
username: ${DATABASE_USERNAME:SYSTEM}
password: ${DATABASE_PASSWORD:12345}
driverClassName: com.kingbase8.Driver
type: com.alibaba.druid.pool.DruidDataSource
mysql:
url: jdbc:mysql://${DATABASE_HOST:127.0.0.1}:${DATABASE_PORT:3306}/${DATABASE_DBNAME:mysql}?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
username: ${DATABASE_USERNAME:root}
password: ${DATABASE_PASSWORD:1234}
driverClassName: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
使用時,只需要在對應(yīng)的mapper上,使用注解@DS(“mysql”),指定當(dāng)前mapper數(shù)據(jù)源為mysql數(shù)據(jù)源
3.多數(shù)據(jù)源失效問題
常見的多數(shù)據(jù)源失效問題可以從配置方面去排查,例如,yml配置,DS指定數(shù)據(jù)源配置等方面。
這里我介紹一下我在使用過程中遇到的多數(shù)據(jù)源失效問題。
問題情境
我在同一個方法中,先調(diào)用了主數(shù)據(jù)源(kingbase)中的某個表數(shù)據(jù),然后再調(diào)用了從數(shù)據(jù)源(mysql)中的數(shù)據(jù),然后執(zhí)行下面業(yè)務(wù)邏輯,我這后面涉及到對數(shù)據(jù)庫的寫操作,我在方法上用了@Transactional注解管理事務(wù),然后我發(fā)現(xiàn),調(diào)用主數(shù)據(jù)源的時候,數(shù)據(jù)獲取正常,調(diào)用從數(shù)據(jù)源的時候,報錯沒有xx表,查看報錯信息為kingbaseSQLException,就知道了調(diào)用的主數(shù)據(jù)源數(shù)據(jù),多數(shù)據(jù)源失效了。于是開始排查
問題排查
(1) 配置問題
首先查看是否是配置原因,檢查yml配置和mapper配置是否正確,然后我寫了個測試接口,測試多數(shù)據(jù)源是否有效,測試接口直接調(diào)用獲取從數(shù)據(jù)源數(shù)據(jù),獲取正確,不是這個原因。
(2)方法代理問題
我將獲取數(shù)據(jù)的代碼單獨封裝方法,然后通過自動注入service,用注入的service調(diào)用方法獲取對應(yīng)所需的數(shù)據(jù),仍然發(fā)現(xiàn)此問題,不是這個原因。
(3)事務(wù)管理問題
這里我查詢了相關(guān)資料,得知在方法上添加事務(wù),事務(wù)只會對一個數(shù)據(jù)源進(jìn)行事務(wù)管理。其實說得通俗易懂一點就是,一個數(shù)據(jù)庫的事務(wù)管不住另一個數(shù)據(jù)庫的事務(wù)。
ok,問題找到現(xiàn)在開始解決問題。
問題解決
根據(jù)我這問題產(chǎn)生原因,思路很簡單,對每個數(shù)據(jù)源數(shù)據(jù)獲取單獨使用事務(wù)管理,這里可以了解一下spring的事務(wù)傳播機制,默認(rèn)傳播機制為Propagation.REQUIRED(如果當(dāng)前沒有事務(wù),就新建一個事務(wù),如果已
經(jīng)存在一個事務(wù)中,加入到這個事務(wù)中),所以在我前面使用方法代理排查問題的時候,還是不行,因為使用的默認(rèn)傳播機制。
這里補充一下事務(wù)傳播機制:
| PROPAGATION_REQUIRED | 如果當(dāng)前沒有事務(wù),就新建一個事務(wù),如果已經(jīng)存在一個事務(wù)中,加入到這個事務(wù)中。這是最常見的選擇。- 默認(rèn) |
|---|---|
| PROPAGATION_SUPPORTS | 支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就以非事務(wù)方式執(zhí)行。 |
| PROPAGATION_MANDATORY | 使用當(dāng)前的事務(wù),如果當(dāng)前沒有事務(wù),就拋出異常。 |
| PROPAGATION_REQUIRES_NEW | 新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起。 |
| PROPAGATION_NOT_SUPPORTED | 以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。 |
| PROPAGATION_NEVER | 以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。 |
| PROPAGATION_NESTED | 如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作 |
基于上面提到的事務(wù)傳播機制,我這將對數(shù)據(jù)庫的操作封裝成獨立方法,然后我使用PROPAGATION_REQUIRES_NEW傳播機制,新建事務(wù),使用方式@Transactional(propagation = Propagation.REQUIRES_NEW)。然后再次測試功能,發(fā)現(xiàn)報另一個錯了,這就說明這個多數(shù)據(jù)源失效問題,已經(jīng)解決。我這的另一個錯產(chǎn)生原因主要是項目中使用到了Neo4j,而這個事務(wù)只支持默認(rèn)事務(wù),所以報錯。
問題解決其他思路
我這因為Neo4j不適合使用多個事務(wù)進(jìn)行事務(wù)管理。所以我這將代碼邏輯進(jìn)行了處理,我將接口的入口方法,單獨封裝方法,然后將數(shù)據(jù)進(jìn)行業(yè)務(wù)邏輯處理后,統(tǒng)一添加到數(shù)據(jù)庫和Neo4j中,這里我將數(shù)據(jù)添加邏輯單獨封裝方法進(jìn)行處理,最后問題解決,功能測試通過。
其實也可以在代碼中不使用@Transcational注解,可以在代碼塊中手動開啟提交回滾事務(wù),也可以達(dá)到效果。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- SpringBoot + Druid + Dynamic Datasource 多數(shù)據(jù)源配置方案
- SpringBoot多數(shù)據(jù)源解決方案:dynamic-datasource-spring-boot-starter
- SpringBoot利用dynamic-datasource-spring-boot-starter解決多數(shù)據(jù)源問題
- springboot dynamic多數(shù)據(jù)源demo以及常見切換、事務(wù)的問題
- springboot項目實現(xiàn)多數(shù)據(jù)源配置使用dynamic-datasource-spring-boot-starter的操作步驟
- Springboot多數(shù)據(jù)源配置之整合dynamic-datasource方式
相關(guān)文章
Java中的排序與內(nèi)部比較器Compareable解析
這篇文章主要介紹了Java中的排序與內(nèi)部比較器Compareable解析,一般沒有特殊要求時,直接調(diào)用(底層默認(rèn)的升序排列)就可以得到想要的結(jié)果,所謂的 sort 方法排序底層都是基于這兩種排序,故如果需要設(shè)計成所想要的排序就需要了解底層排序原理,需要的朋友可以參考下2023-11-11
一文探索Apache HttpClient如何設(shè)定超時時間
Apache HttpClient是一個流行的Java庫,用于發(fā)送HTTP請求,這篇文章主要為大家介紹了Apache HttpClient如何設(shè)定超時時間,感興趣的小伙伴可以學(xué)習(xí)一下2023-10-10
Java實現(xiàn)雙鏈表互相交換任意兩個節(jié)點的方法示例
這篇文章主要介紹了Java實現(xiàn)雙鏈表互相交換任意兩個節(jié)點的方法,簡單講述了雙鏈表的概念,并結(jié)合實例形式給出了java雙鏈表實現(xiàn)任意兩個節(jié)點交換的操作技巧,需要的朋友可以參考下2017-11-11
Mybatis 如何批量刪除數(shù)據(jù)的實現(xiàn)示例
這篇文章主要介紹了Mybatis 如何批量刪除數(shù)據(jù)的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03

