---
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交易偶會碰到的問題:
* 
雖然之前有看過但實際遇過還是紀錄一下:
具體原因是因為,<span class="emphasis-red">多層嵌套事務中,如果使用了默認的事務傳播方式,當內層事務拋出異常,外層事務捕捉並正常執行完畢時,就會報出rollback-only異常</span>
簡單說就是如下圖:

<br>
寫了一個小專案模擬,程式片段如下:
* **DB資料**

* **EmpService.java**

* **DeptService.java**

* **測試程式 TestMain.java**

---
> <span class="emphasis-blue italic">Solution:調整被呼叫方的交易傳播行為(Propagatcion)為 Nested</span>
* 
* 再測試一次,console無錯誤且DB也成功異動

* 
---
>後記:
> 在公司專案使用此解法似乎仍發生 marked as rollback only 錯誤
推測可能是因為公司專案使用了Spring Xml配置AOP,與我想混用@Transaction的關係,後來還是使用了比較LOW的解法:
1. 先查一次看有TABLE中是否已存在此PK的資料
2. 若有即先刪除
3. 若無直接新增
---
> 補充:NESTED傳播行為 (ref. [昕力](https://www.tpisoftware.com/tpu/articleDetails/2092))

<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)