在觀看此篇文章以前須要瞭解什麼是事務的傳播屬性git
在觀看此篇文章以前須要瞭解什麼是事務的傳播屬性github
在觀看此篇文章以前須要瞭解什麼是事務的傳播屬性post
Transaction rolled back because it has been marked as rollback-only3d
相信你們在使用Spring事務的時候有機率會碰到一個異常,這個異常就是UnexpectedRollbackException
異常的描述就是上面所寫的。至於這個異常是怎麼報出來的呢?咱們先模擬出來,而後進行着手分析。咱們模擬的場景是轉錢的場景,即A給B轉100塊錢。code
@Service public class UserAccountA { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private UserAccountB userAccountB; @Transactional public void eventTwo() throws RollbackException { jdbcTemplate.execute("UPDATE USER SET MONEY = MONEY - 100 WHERE NAME = 'A'"); userAccountB.eventTwo(); } }
@Service public class UserAccountB { @Autowired private JdbcTemplate jdbcTemplate; @Transactional(propagation = Propagation.REQUIRED,rollbackFor = RollbackException.class) public void eventTwo() throws RollbackException { jdbcTemplate.execute("UPDATE USER SET MONEY = MONEY + 100 WHERE NAME = 'B'"); throw new RollbackException(); } }
public class RollbackException extends Exception { }
上面的三個類分別是用戶A、用戶B、和自定義的異常。這時候咱們運行程序的時候就能看到那個異常了。那麼爲何會報此異常呢。這裏咱們有兩個須要注意的點。blog
Propagation.REQUIRED
此傳播屬性下的意思就是支持當前事務,若是當前沒有事務那麼就新建事務,若是有事務就加入此事務。因此此時B方法加入到了A方法建立的事務中Exception
。下面的是官方文檔的一句話,意思就是默認狀況下當拋出RuntimeException
纔會回滾。By default, a transaction will be rolling back RuntimeException and Error繼承
有了上面兩個知識的補充,下面咱們開始講爲何會報這個異常,咱們都知道Spring的事務實際上是用了動態搭理的原理實現的。事務
大概嵌套邏輯就像上圖同樣,可是在B方法執行完成之後拋出了異常,須要回滾,可是並不會真正的回滾,而是將此事務標記爲rollback-only
,當A方法執行完之後,咱們能夠看到在A方法上面並無rollbackFor
這個參數設置,而拋出的異常也是繼承了Exception
因此A方法執行完之後想要提交事務,因此此時就會產生衝突。文檔
同一個事務中,一個方法想要回滾,一個方法想要提交。固然會拋異常了。get
解決辦法很簡單,首先咱們看是什麼致使了這個問題。同一個事務中,一個方法想要回滾,一個方法想要提交。。致使這個問題緣由有兩個。
因此針對上面緣由咱們能夠有兩種不一樣的解決方法。
PROPAGATION_REQUIRES_NEW
,即不會和A共用一個事務,會本身新啓動一個事務。此時A和B兩個方法互不干擾。rollbackFor = RollbackException.class
參數,此時A方法收到B方法拋出的異常後,也會回滾了。