您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么理解Spring雙層事務”,在日常操作中,相信很多人在怎么理解Spring雙層事務問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解Spring雙層事務”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
系統 A 調用系統 B 執行數據同步,系統 B 返回了錯誤提示,系統 A 需要將前邊保存的回滾掉,同時把錯誤信息向上拋。
@Service("noteService") public class NoteServiceImpl implements NoteService { @Resource private SearchService searchService; @Transactional(rollbackFor = Throwable.class) @Override public CommonResponse<NoteEntity> save(NoteEntity note) { // 一系列 DB 操作 try { searchService.sync(note); } catch (Exception e) { e.printStackTrace(); } return CommonResponse.success(entity); } }
@Service("searchService") public class SearchServiceImpl implements SearchService { @Transactional(rollbackFor = Throwable.class) @Override public void sync(NoteEntity note) { // 一系列 DB 操作 throw new RuntimeException("同步異常! [XXX]"); } }
@SpringBootTest public class NoteTests { @Resource private NoteService noteService; @Test public void saveNote() { NoteEntity entity = new NoteEntity(); entity.setTitle("念奴嬌赤壁懷古"); entity.setContent("大江東去,浪淘盡,千古風流人物。故壘西邊,人道是:三國周郎赤壁。。。"); entity.setTags("蘇軾,宋代"); entity.setCategory("蘇軾詩詞"); try { noteService.save(entity); } catch (Exception e) { e.printStackTrace(); // FIXME 我想在這里拿到的是 同步異常! [XXX] // FIXME 但是這里拿到的是 Transaction silently rolled back because it has been marked as rollback-only System.out.println(">>>>>>>>>> " + e.getMessage()); } } }
代碼歷史久遠,為何這樣寫已無從追溯。
納悶了一會兒,看到雙層事務,就想起了 Spring事務傳播機制,前邊理解得比較膚淺。
沒有特殊的配置,自然是走默認的事務傳播機制了,也就是 Propagation.REQUIRED。
國際慣例,列出事務傳播機制:
1、PROPAGATION_REQUIRED 當前沒事務,則創建事務;存在事務,就加入該事務,這是最常用的設置。 2、PROPAGATION_SUPPORTS 當前存在事務,就加入事務,當前不存在事務,就以非事務方式執行。 3、PROPAGATION_MANDATORY 當前存在事務,就加入事務;當前不存在事務,就拋出異常。 4、PROPAGATION_REQUIRES_NEW 無條件創建新事務。 5、PROPAGATION_NOT_SUPPORTED 以非事務方式執行,如果當前存在事務,就將當前事務掛起。 6、PROPAGATION_NEVER 以非事務方式運行,如果存在事務,就拋出異常。 7、PROPAGATION_NESTED 開始執行事務前,先保存一個savepoint,當發生異常時,就回滾到savepoint;沒有異常時,跟著外部事務一起提交或回滾。
1、看了上邊的事務傳播機制,繼續細化問題,內外層共用一個事務,內層拋出異常,會導致整個事務失敗。
2、繼續分析,外層邏輯進行了 try catch,就導致內層的異常無法繼續向上拋出,外層事務會繼續提交。
3、事務提交時,進行事務狀態的判斷,就發現這個事務是失敗的,需要回滾,所以拋出了 Transaction silently rolled back because it has been marked as rollback-only
的異常。
銀彈自然是沒有的,根據業務場景選擇合適的方案。
1、當前這種場景,直接把外層邏輯中的 try catch 去掉即可。異常直接向上拋,事務就不會繼續提交,調用方拿到的就是一手的異常;
2、如果內層不是核心邏輯,記錄個日志啥的,可以把內層事務配置為 @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRES_NEW)
, 無論如何,都創建新的事務,外層事務不受內層事務影響。但是有個問題,外層事務失敗了,內層事務還是把記錄入庫了,有可能產生臟數據;
3、如果外層事務失敗了,內層事務也不能提交,那就可以使用 @Transactional(rollbackFor = Throwable.class, propagation = Propagation.NESTED)
。 注意:hibernate/jpa 不支持嵌套事務 NESTED,可用 JdbcTemplate 代替。
到此,關于“怎么理解Spring雙層事務”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。