[英]Spring Data: rollback transaction on retry
有一個實體:
@Entity
class A {
...
@Version
int version;
}
A
實例更新的樂觀的方式來實現:
@Transactional(rollbackFor = {StaleStateException.class})
@Retryable(value = {StaleStateException.class})
public void updateA() {
A a = findA();
B b = new B();
// Update "a" somehow
a.update();
// "b" is saved on each retry!
save(b);
}
如注釋中所述,似乎發生StaleStateException
時事務不會回滾,因此每次重試時都會保存B
實例。
是否可以在重試時回滾事務?
期望的行為是b
僅在全成保存a
更新。
我認為它可能與@Retryable
配置有關。
正如文檔所述https://docs.spring.io/spring-batch/trunk/reference/html/retry.html#statelessRetry一樣 ,無狀態可重試只不過是一個循環,它一直調用相同的方法直到它成功。
問題是,每次失敗時,第一個被調用的攔截器都是可重試的,不會重新拋出異常,因此它永遠不會到達@Transactional
。
所以會發生的是,每次重試都將遵循默認的事務傳播,這將在上下文中重用相同的已打開事務和new B()
。
您可以通過調試檢查我是否在正確的線索上:如果您輸入第二次重試並發現A
在更新塊之前已經更新,那么我應該是正確的。
您可以通過兩種方式修復:
將兩個塊分開(首先使用嵌套事務重試)
@Retryable(value = {StaleStateException.class})
public void retryableUpdate() {
updateA();
}
@Transactional(rollbackFor = {StaleStateException.class})
public void updateA() {
A a = findA();
B b = new B();
// Update "a" somehow
a.update();
// "b" is saved on each retry!
save(b);
}
這樣事務就會先回滾。
或者您可以關注文檔並使用有狀態重試https://docs.spring.io/spring-batch/trunk/reference/html/retry.html#statefulRetry
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.