--- tags: Java, Spring, Transaction --- <style> .center { text-align: center; } .emphasis-red { color: #EA0000; font-weight: bold; } .emphasis-blue { color: #0000C6; font-weight: bold; } .italic { font-style: italic; } </style> # Spring 交易 : Transaction rolled back because it has been marked as rollback-only 前陣子在開發公司專案的需求時,有個部分需要根據DB是否已有重複Primary-Key進行處理 <span class="emphasis-blue">若已有重複PK的資料,則先進行刪除舊資料後,再進行一次INSERT</span> 蠻EASY的需求,但是卻發生了如title所述的錯誤,GOOGLE了一下發現是一個使用Spring交易偶會碰到的問題: * ![Google Result](https://i.imgur.com/TzzRSTQ.png) 雖然之前有看過但實際遇過還是紀錄一下: 具體原因是因為,<span class="emphasis-red">多層嵌套事務中,如果使用了默認的事務傳播方式,當內層事務拋出異常,外層事務捕捉並正常執行完畢時,就會報出rollback-only異常</span> 簡單說就是如下圖: ![示意圖](https://i.imgur.com/OJhPjFs.png) <br> 寫了一個小專案模擬,程式片段如下: * **DB資料** ![](https://i.imgur.com/UagQ3iX.png) * **EmpService.java** ![](https://i.imgur.com/7AyoqLX.png) * **DeptService.java** ![](https://i.imgur.com/TYvo9fQ.png) * **測試程式 TestMain.java** ![](https://i.imgur.com/CeRnsGk.png) --- > <span class="emphasis-blue italic">Solution:調整被呼叫方的交易傳播行為(Propagatcion)為 Nested</span> * ![](https://i.imgur.com/Bnn0M0T.png) * 再測試一次,console無錯誤且DB也成功異動 ![](https://i.imgur.com/eOqcn6F.png) * ![](https://i.imgur.com/RoHHjVq.png) --- >後記: > 在公司專案使用此解法似乎仍發生 marked as rollback only 錯誤 推測可能是因為公司專案使用了Spring Xml配置AOP,與我想混用@Transaction的關係,後來還是使用了比較LOW的解法: 1. 先查一次看有TABLE中是否已存在此PK的資料 2. 若有即先刪除 3. 若無直接新增 --- > 補充:NESTED傳播行為 (ref. [昕力](https://www.tpisoftware.com/tpu/articleDetails/2092)) ![](https://i.imgur.com/JuclKBq.png) <br> --- <br> > 參考資料: 1. https://reurl.cc/gW8rjL 2. https://www.itread01.com/content/1550579227.html 3. https://www.tpisoftware.com/tpu/articleDetails/2092 4. Github Repo: [SpringTransactionRollbackOnlyTest](https://github.com/sobadrush/SpringTransactionRollbackOnlyTest)