是否有任何方法「重放」事務? 我的意思是,有時我會得到RollbackException並回滾事務。然後,我可以「克隆」交易並再次嘗試,或者一旦調用回滾,交易就會丟失? 我真的需要改變了,真的不想追查後重新運行的每一個變化...在Java中處理RollbackException
感謝, UDI
是否有任何方法「重放」事務? 我的意思是,有時我會得到RollbackException並回滾事務。然後,我可以「克隆」交易並再次嘗試,或者一旦調用回滾,交易就會丟失? 我真的需要改變了,真的不想追查後重新運行的每一個變化...在Java中處理RollbackException
感謝, UDI
爲什麼你擺在首位的例外呢?這在我看來是問題的關鍵。
你是依靠樂觀寫作嗎?如果是這樣,那麼你將不得不以某種形式的循環包裝你的數據庫寫入,包含(可能)退避和一些重試。不幸的是,你不能自動做到這一點(除非你調查某種形式的包裝你的數據庫的解決方案寫入重試策略?)
這取決於交易來自哪裏。在Java/JDBC中,事務與連接相關聯。您可以通過將setAutoCommit()
設置爲false來啓動它(否則,每條語句都會成爲它自己的小事務)。
在事務失敗後(即您稱爲回滾),沒有什麼能夠阻止您重新使用連接。
當你使用Spring時,事情變得更加棘手。 Spring將你的方法封裝在一個事務處理器中,並且這個處理器試圖猜測它應該如何處理來自方法中拋出的異常的當前事務。接下來的問題是:哪個包裝器創建了當前事務?我只是遇到了一種情況,我會調用方法foo()
,該方法將依次調用bar()
,這兩個都是@Transactional
。
我想從bar()
的foo()
中發現錯誤並將它們保存到數據庫中。這是行不通的,因爲交易是爲foo()
創建的(所以我仍然處於Spring認爲由於bar()
中的例外而被破壞的交易),並且它不會讓我保存錯誤。
解決方案是創建baz()
,使其爲@Transactional(propagation=Propagation.REQUIRES_NEW)
並從foo()
調用它。 baz()
會得到一個新的新鮮事務,並且即使從foo()
調用了已經有(斷開)事務的數據庫,也可以寫入數據庫。
另一種替代方法是使用JDBC savepoints部分回滾。
據我所知,在這種特定情況下,保存位並沒有幫助,因爲回滾到最後的保存點不會保留稍後更新的數據。 – Udi 2009-11-03 12:30:52