Spring 事務(wù)傳播行為和隔離級(jí)別的應(yīng)用

一言蔽之

對(duì)Spring事務(wù)了解一直處于理論階段,幾個(gè)事務(wù)傳播行為(propagation behaviors),幾個(gè)隔離級(jí)別(isolation levels)看了又忘,忘了又看。近期的開發(fā)中遇到了幾個(gè)有趣的例子,拿出來曬曬。

具體應(yīng)用

1. 在catch塊中,繼續(xù)進(jìn)行數(shù)據(jù)庫操作

場(chǎng)景

以下是簡(jiǎn)化后的Kotlin代碼
execute()在事務(wù)內(nèi)執(zhí)行
doSomeThing()可能會(huì)拋出RuntimeException
fail() 會(huì)對(duì)數(shù)據(jù)庫有一些修改操作


@Transactional
override fun execute() {
    try {
        doSomeThing()
    } catch (e: Exception) {
        fail()
    }
}

override fun fail() {
   saveLogToDB()
}

問題
如果doSomeThing()拋出RuntimeException,fail()在執(zhí)行數(shù)據(jù)庫操作時(shí),會(huì)拋出異常:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

分析&思路

  1. 方法saveLogToDB()執(zhí)行時(shí)事務(wù)已經(jīng)被標(biāo)記為rollback-only
  2. saveLogToDB()使用的事務(wù)是在execute()方法執(zhí)行之前創(chuàng)建的
  3. doSomeThing()執(zhí)行的某個(gè)步驟中,因?yàn)橛|發(fā)異常,事務(wù)被標(biāo)記為rollback-only
  4. 那么,為了saveLogToDB()能夠保存數(shù)據(jù)到數(shù)據(jù)庫,就不能夠使用execute()方法的事務(wù)了。

回憶以下有哪些事務(wù)的傳播行為:

// 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。
    // @Transactional 注解默認(rèn)采用這個(gè)方案
    REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

    // 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。
    SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

    // 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。
    MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

     // 創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
    REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

    // 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
    NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

    // 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。
    NEVER(TransactionDefinition.PROPAGATION_NEVER),

    // 如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運(yùn)行;如果當(dāng)前沒有事務(wù),則該取值等價(jià)于REQUIRED
    // 并非所有的TransactionManager都能支持這個(gè)傳播級(jí)別
    NESTED(TransactionDefinition.PROPAGATION_NESTED);

作者:whthomas
鏈接:http://www.itdecent.cn/p/e56b440e9eb6
來源:簡(jiǎn)書
簡(jiǎn)書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處。

顯然,這里需要使用REQUIRES_NEW傳播行為。

解決
fail()方法上加上事務(wù),并讓propagation = REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRES_NEW)
override fun fail() {
   saveLogToDB()
}

注意:同一個(gè)類中,方法間調(diào)用,事務(wù)AOP生效的前提條件是使用CGLIB方式實(shí)現(xiàn)AOP。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 事務(wù),是為了保障邏輯處理的原子性、一致性、隔離性、永久性。 通過事務(wù)控制,可以避免因?yàn)檫壿嬏幚硎《鴮?dǎo)致產(chǎn)生臟數(shù)據(jù)...
    uzip柚子皮閱讀 4,821評(píng)論 3 16
  • 事務(wù)的嵌套概念 所謂事務(wù)的嵌套就是兩個(gè)事務(wù)方法之間相互調(diào)用。spring事務(wù)開啟 ,或者是基于接口的或者是基于類的...
    jackcooper閱讀 1,504評(píng)論 0 10
  • 很多人喜歡這篇文章,特此同步過來 由淺入深談?wù)搒pring事務(wù) 前言 這篇其實(shí)也要?dú)w納到《常識(shí)》系列中,但這重點(diǎn)又...
    碼農(nóng)戲碼閱讀 4,936評(píng)論 2 59
  • 從前有一個(gè)老人,他有三個(gè)兒子。 有一天,三個(gè)兒子開始比絕招,大兒子出了一個(gè)謎題,樹上七只猴,地下一只猴,一共有幾只...
    猴一棒閱讀 255評(píng)論 0 2
  • 了解了窮文富武的概念。 高考的公平在于比起大城市的優(yōu)良素質(zhì)教育,給廣大農(nóng)村及不富裕的地區(qū)的孩子一個(gè)只要肯下功夫把書...
    cuijieshi閱讀 330評(píng)論 0 0

友情鏈接更多精彩內(nèi)容