[英]Run spring @Transactional annotated methods in a single transaction
[英]Do @Transactional annotated methods wait for a successful commit in Spring?
在Spring中使用@Transactional
注解方法時,注解方法的返回是否與底層數據庫事務的成功提交同步?
(這是假設事務在返回后實際上會提交,這可能不是這種情況,具體取決於所選的傳播方法。)
如果等待提交不是默認行為,有沒有辦法通過配置或其他方式啟用它?
我的問題的動機是我想實現一個可靠的“存儲和轉發”類型的端點,它只在調用的影響被提交到穩定存儲后才向客戶端返回響應。 @Transactional
完全可以做到這一點嗎?
簡短的回答是否定的:該方法不等待提交。
實際發生的情況取決於兩個因素:
如果沒有事務預先存在,則在調用該方法之前創建一個新事務,並且如果它沒有被標記為僅回滾,則 Spring 會嘗試在該方法返回后立即提交它 - 在這種情況下,即使該方法不等待對於提交,立即執行提交。
由於嵌套調用,在物理事務已經存在的情況下調用事務性注釋方法時,事情會變得更難
摘自 Spring 參考手冊:
當傳播設置為 PROPAGATION_REQUIRED 時,將為應用該設置的每個方法創建一個邏輯事務范圍。 每個這樣的邏輯事務范圍可以單獨確定僅回滾狀態,外部事務范圍在邏輯上獨立於內部事務范圍。 當然,在標准 PROPAGATION_REQUIRED 行為的情況下,所有這些范圍都將映射到同一個物理事務。 因此,在內部事務范圍內設置的僅回滾標記確實會影響外部事務實際提交的機會
PROPAGATION_REQUIRES_NEW 與 PROPAGATION_REQUIRED 不同,它為每個受影響的事務范圍使用一個完全獨立的事務。 在這種情況下,底層物理事務是不同的,因此可以獨立提交或回滾,外部事務不受內部事務回滾狀態的影響。
PROPAGATION_NESTED 使用具有多個可以回滾到的保存點的單個物理事務。 這種部分回滾允許內部事務作用域觸發其作用域的回滾,而外部事務能夠繼續物理事務,盡管某些操作已經回滾。
這意味着除了 PROPAGATION_REQUIRES_NEW,在包含事務結束之前不會嘗試提交。
換句話說,如果您希望在事務注釋方法結束后立即進行提交,則必須將傳播設置為 PROPAGATION_REQUIRES_NEW : @Transactional(propagation=Propagation.REQUIRES_NEW)
如果您沒有使用@Transactional
,那么您將如何處理它? 它將是類似的代碼塊,如下所示
UserTransaction utx = entityManager.getTransaction();
try {
utx.begin();
businessLogic();
utx.commit();
} catch(Exception ex) {
utx.rollback();
throw ex;
}
@Transactional
實際上為你做同樣的事情。 所以你可以看到它是在你的業務邏輯之后處理的。
我從這個精彩的博客中復制了代碼。 您可以查看此內容以了解更多詳細信息。
我使用了參數isolation = Isolation.SERIALIZABLE
,所以一個方法會在事務實際提交后完成。 (順便說一下,我將 @Transactional 放在 Spring boot 項目中的控制器方法之上。)
我在保存事務中嘗試了 PROPAGATION_REQUIRES_NEW,這對我有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.