SpringBoot項目中用到多數據源,在方法上又必須加事務處理,此時可以對使用了@DS的方法或類添加@Transactional並添加事務隔離級別
舉例:
1、這是一個方法,方法內需要實現多數據源查詢
2、在該方法中判斷查詢哪一個數據源:
3、此時可以將slave數據源的service類添加
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
原因解析
解決辦法就是將原本的一個事務拆分成兩個事務。你可以試一下,只在主方法中加事務,你會發現在切面裏看數據源切換了,但事務內的數據源依然是舊的,這樣就會報出XXX表找不到的問題。那麼到底是什麼原因導致一個事務內的數據源沒有隨着@DS(“slave”)註解做出動態數據源切換呢?
因爲SPRING在開啓事務的同時,會去數據庫連接池拿數據庫連接。如果僅在主方法上添加@TRANSACTIONAL,那麼,TRANSACTIONINTERCEPTOR 會使用 SPRING DATASOURCETRANSACTIONMANAGER 創建事務,並將事務信息(獲取數據源CONNECTION連接,此時獲取到的數據源是默認配置的BASE數據源信息)連接信息,通過 THREADLOCAL 綁定在當前線程。
此時當前線程事務綁定的連接信息是BASE數據源,當我們在內層切換數據源方法上使用@DS切換數據源,並沒有重新開啓新事務,沒有改變當前線程事務的連接信息,僅僅是做了一次攔截,改變了DATASOURCEHOLDER的棧頂DATASOURCE,對於整個事務的連接是沒有影響的,所以會產生數據源沒有切換的問題。
所以我這裏的解決辦法是,將保證住方法操作數據完整性的事務,拆解成兩個事務,在切換數據源方法類上,除了添加切換數據源的註解@DS(“DB2”),再添加@TRANSACTIONAL(PROPAGATION = PROPAGATION.REQUIRES_NEW, ROLLBACKFOR = EXCEPTION.CLASS),新建開一個事務,獲取新數據源CONNECTION連接。
在使用
@DS
註解時,有如下注意事項:
- 不能使用事務,否則數據源不會切換,使用的還是第一次加載的數據源;
- 第一次加載數據源之後,第二次、第三次…操作其它數據源,如果數據源不存在,使用的還是第一次加載的數據源;
- 數據源名稱不要包含下劃線,否則不能切換。
一句話總結:用到多數據源的方法不能使用事務,如果主方法必須使用事務,那麼slave數據源方法上或類上需要添加 下面註解。
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)