文章參考資料 https://www.cnblogs.com/andy-zhou/p/5317866.html
http://labreeze.iteye.com/blog/2277261
Spring 事務的傳遞性介紹
事務傳播行為,所謂事務的傳播行為是指,如果在開始當前事務之前,一個事務上下文已經存在,此時有若干選項可以指定一個事務性方法的執行行為。在TransactionDefinition定義中包括了如下幾個表示傳播行為的常量:
TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:創建一個新的事務,如果當前存在事務,則把當前事務掛起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。
TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。
TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價TransactionDefinition.PROPAGATION_REQUIRED。
這里需要指出的是,前面的六種事務傳播行為是 Spring 從 EJB 中引入的,他們共享相同的概念。而 PROPAGATION_NESTED是 Spring 所特有的。以 PROPAGATION_NESTED 啟動的事務內嵌於外部事務中(如果存在外部事務的話),此時,內嵌事務並不是一個獨立的事務,它依賴於外部事務的存在,只有通過外部的事務提交,才能引起內部事務的提交,嵌套的子事務不能單獨提交。如果熟悉 JDBC 中的保存點(SavePoint)的概念,那嵌套事務就很容易理解了,其實嵌套的子事務就是保存點的一個應用,一個事務中可以包括多個保存點,每一個嵌套子事務。另外,外部事務的回滾也會導致嵌套子事務的回滾。
場景
在同一個類或者不同類,controller層調用方法A,在方法A中,調用方法B,事務的傳播機制
這個是實際開發中的場景
方法A與方法B在同一個類中
結論
同一個service中,被外部調用的方法A如果有事務,則方法A中所有方法均會使用方法A的事務,且子方法的事務失效
方法A與方法B在不同一個類中
結論
不同一個service中,被外部調用的方法A如果有事務,則方法A中所有方法均會默認使用方法A的事務,如果B有事務,B會使用B的事務
最后結論
被外部調用的方法A如果有事務,則方法A中所有方法均會使用方法A的事務,
在同類中子方法事務失效,
不同類子方法事務生效
新增操作回滾后,Id值已經被增加,不會回滾
問題
為什么同一個類中事務不能傳遞
答:我們知道,Spring之所以可以對開啟@Transactional的方法進行事務管理,是因為Spring為當前類生成了一個代理類,然后在執行相關方法時,會判斷這個方法有沒有@Transactional注解,如果有的話,則會開啟一個事務。
但是,上面這種調用方式時,在調用方法B時,使用的並不是代理對象,從而導致調用方法B時也不是代碼對象,從而導致@Transactional失敗。
解決:
1)xml 配置 <aop:aspectj-autoproxy expose-proxy="true"/>
2)注解 @EnableAspectJAutoProxy(exposeProxy=true)表示通過aop框架暴露該代理對象,aopContext能夠訪問 ((Bean) AopContext.currentProxy()).methodB();
3)ApplicationContextUtils.applicationContext(Bean).methodB