摘要:在嵌套事務(wù)場(chǎng)景中,內(nèi)層事務(wù)的和外層事務(wù)的會(huì)在外層事務(wù)結(jié)束時(shí)進(jìn)行提交或回滾。解決方案如果希望內(nèi)層事務(wù)拋出異常時(shí)中斷程序執(zhí)行,直接在外層事務(wù)的代碼塊中拋出如果希望程序正常執(zhí)行完畢,并且希望外層事務(wù)結(jié)束時(shí)全部提交,需要在內(nèi)層事務(wù)中做異常捕獲處理。
前言
最近在項(xiàng)目中發(fā)現(xiàn)了一則報(bào)錯(cuò):“org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only”。根據(jù)報(bào)錯(cuò)信息來(lái)看是spring框架中的事務(wù)管理報(bào)錯(cuò):事務(wù)回滾了,因?yàn)樗粯?biāo)記為回滾狀態(tài)。
報(bào)錯(cuò)原因多層嵌套事務(wù)中,如果使用了默認(rèn)的事務(wù)傳播方式,當(dāng)內(nèi)層事務(wù)拋出異常,外層事務(wù)捕捉并正常執(zhí)行完畢時(shí),就會(huì)報(bào)出rollback-only異常。
spring框架是使用AOP的方式來(lái)管理事務(wù),如果一個(gè)被事務(wù)管理的方法正常執(zhí)行完畢,方法結(jié)束時(shí)spring會(huì)將方法中的sql進(jìn)行提交。如果方法執(zhí)行過(guò)程中出現(xiàn)異常,則回滾。spring框架的默認(rèn)事務(wù)傳播方式是PROPAGATION_REQUIRED:如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù),如果已經(jīng)存在一個(gè)事務(wù)中,加入到這個(gè)事務(wù)中。
在項(xiàng)目中,一般我們都會(huì)使用默認(rèn)的傳播方式,這樣無(wú)論外層事務(wù)和內(nèi)層事務(wù)任何一個(gè)出現(xiàn)異常,那么所有的sql都不會(huì)執(zhí)行。在嵌套事務(wù)場(chǎng)景中,內(nèi)層事務(wù)的sql和外層事務(wù)的sql會(huì)在外層事務(wù)結(jié)束時(shí)進(jìn)行提交或回滾。如果內(nèi)層事務(wù)拋出異常e,在內(nèi)層事務(wù)結(jié)束時(shí),spring會(huì)把事務(wù)標(biāo)記為“rollback-only”。這時(shí)如果外層事務(wù)捕捉了異常e,那么外層事務(wù)方法還會(huì)繼續(xù)執(zhí)行代碼,直到外層事務(wù)也結(jié)束時(shí),spring發(fā)現(xiàn)事務(wù)已經(jīng)被標(biāo)記為“rollback-only”,但方法卻正常執(zhí)行完畢了,這時(shí)spring就會(huì)拋出“org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only”。
代碼示例如下:
Class ServiceA { @Resource(name = "serviceB") private ServiceB b; @Transactional public void a() { try { b.b() } catch (Exception ignore) { } } } Class ServiceB { @Transactional public void b() { throw new RuntimeException(); } }
當(dāng)調(diào)用a()時(shí),就會(huì)報(bào)出“rollback-only”異常。
解決方案如果希望內(nèi)層事務(wù)拋出異常時(shí)中斷程序執(zhí)行,直接在外層事務(wù)的catch代碼塊中拋出e.
如果希望程序正常執(zhí)行完畢,并且希望外層事務(wù)結(jié)束時(shí)全部提交,需要在內(nèi)層事務(wù)中做異常捕獲處理。
如果希望內(nèi)層事務(wù)回滾,但不影響外層事務(wù)提交,需要將內(nèi)層事務(wù)的傳播方式指定為PROPAGATION_NESTED。注:PROPAGATION_NESTED基于數(shù)據(jù)庫(kù)savepoint實(shí)現(xiàn)的嵌套事務(wù),外層事務(wù)的提交和回滾能夠控制嵌內(nèi)層事務(wù),而內(nèi)層事務(wù)報(bào)錯(cuò)時(shí),可以返回原始savepoint,外層事務(wù)可以繼續(xù)提交。
在我的項(xiàng)目中之所以會(huì)報(bào)“rollback-only”異常的根本原因是代碼風(fēng)格不一致的原因。外層事務(wù)對(duì)錯(cuò)誤的處理方式是返回true或false來(lái)告訴上游執(zhí)行結(jié)果,而內(nèi)層事務(wù)是通過(guò)拋出異常來(lái)告訴上游(這里指外層事務(wù))執(zhí)行結(jié)果,這種差異就導(dǎo)致了“rollback-only”異常。雖然最后事務(wù)依然是回滾了,不影響程序?qū)ql的處理,但外層事務(wù)的上游本期望返回true和false,卻收到了UnexpectedRollbackException異常,(╯ ̄Д ̄)╯︵ ┻━┻。
附:事務(wù)傳播方式@see org.springframework.transaction.annotation.Propagation
事務(wù)傳播方式 | 說(shuō)明 |
---|---|
PROPAGATION_REQUIRED | 如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù),如果已經(jīng)存在一個(gè)事務(wù)中,加入到這個(gè)事務(wù)中。這是默認(rèn)的傳播方式 |
PROPAGATION_SUPPORTS | 支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就以非事務(wù)方式執(zhí)行 |
PROPAGATION_MANDATORY | 使用當(dāng)前的事務(wù),如果當(dāng)前沒(méi)有事務(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_SUPPORTS | 支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就以非事務(wù)方式執(zhí)行。 |
PROPAGATION_NESTED | 如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒(méi)有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類似的操作。 |
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77135.html
摘要:題目假設(shè)高度已知,請(qǐng)寫(xiě)出三欄布局,其中左欄右欄寬度各為,中間自適應(yīng)三欄布局的種方案這是一道經(jīng)典的面試題,下面記錄了布局的種方法。 題目:假設(shè)高度已知,請(qǐng)寫(xiě)出三欄布局,其中左欄、右欄寬度各為300px,中間自適應(yīng). 三欄布局的5種方案 這是一道經(jīng)典的面試題,下面記錄了css布局的5種方法。 三欄布局 * { margin: 0; ...
摘要:前言三欄布局,顧名思義就是兩邊固定,中間自適應(yīng)。三欄布局在實(shí)際的開(kāi)發(fā)十分常見(jiàn),比如淘寶網(wǎng)的首頁(yè),就是個(gè)典型的三欄布局即左邊商品導(dǎo)航和右邊導(dǎo)航固定寬度,中間的主要內(nèi)容隨瀏覽器寬度自適應(yīng)。但網(wǎng)格布局的兼容性不好。 前言 三欄布局,顧名思義就是兩邊固定,中間自適應(yīng)。三欄布局在實(shí)際的開(kāi)發(fā)十分常見(jiàn),比如淘寶網(wǎng)的首頁(yè),就是個(gè)典型的三欄布局:即左邊商品導(dǎo)航和右邊導(dǎo)航固定寬度,中間的主要內(nèi)容隨瀏覽器寬...
摘要:前言三欄布局,顧名思義就是兩邊固定,中間自適應(yīng)。三欄布局在實(shí)際的開(kāi)發(fā)十分常見(jiàn),比如淘寶網(wǎng)的首頁(yè),就是個(gè)典型的三欄布局即左邊商品導(dǎo)航和右邊導(dǎo)航固定寬度,中間的主要內(nèi)容隨瀏覽器寬度自適應(yīng)。但網(wǎng)格布局的兼容性不好。 前言 三欄布局,顧名思義就是兩邊固定,中間自適應(yīng)。三欄布局在實(shí)際的開(kāi)發(fā)十分常見(jiàn),比如淘寶網(wǎng)的首頁(yè),就是個(gè)典型的三欄布局:即左邊商品導(dǎo)航和右邊導(dǎo)航固定寬度,中間的主要內(nèi)容隨瀏覽器寬...
摘要:前言三欄布局,顧名思義就是兩邊固定,中間自適應(yīng)。三欄布局在實(shí)際的開(kāi)發(fā)十分常見(jiàn),比如淘寶網(wǎng)的首頁(yè),就是個(gè)典型的三欄布局即左邊商品導(dǎo)航和右邊導(dǎo)航固定寬度,中間的主要內(nèi)容隨瀏覽器寬度自適應(yīng)。但網(wǎng)格布局的兼容性不好。 前言 三欄布局,顧名思義就是兩邊固定,中間自適應(yīng)。三欄布局在實(shí)際的開(kāi)發(fā)十分常見(jiàn),比如淘寶網(wǎng)的首頁(yè),就是個(gè)典型的三欄布局:即左邊商品導(dǎo)航和右邊導(dǎo)航固定寬度,中間的主要內(nèi)容隨瀏覽器寬...
閱讀 707·2021-11-15 11:37
閱讀 3326·2021-10-27 14:14
閱讀 6121·2021-09-13 10:30
閱讀 2970·2021-09-04 16:48
閱讀 1940·2021-08-18 10:22
閱讀 2137·2019-08-30 14:19
閱讀 739·2019-08-30 10:54
閱讀 1756·2019-08-29 18:40