Spring 傳播行爲java
Spring 中定義的七種傳播行爲,由於Spring將事務傳播行爲是交給事務管理器去實現的,因此使用以前第一步就是查看咱們使用的事務管理器是否支持下面的七中傳播行爲:spring
PROPAGATION_REQUIRED - -支持當前事務,若是當前沒有事務,就新建一個事務。這是最多見的選擇。
PROPAGATION_SUPPORTS - -支持當前事務,若是當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY - -支持當前事務,若是當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW - -新建事務,若是當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED - -以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER - -以非事務方式執行,若是當前存在事務,則拋出異常。 測試
我使用的是:org.springframework.jdbc.datasource.DataSourceTransactionManager 並非徹底是支持這七種傳播行爲的因此就有不少問題,使用其餘的時候必定要關注一下,開始被坑哭了(DataSourceTransactionManager 不支持 PROPAGATION_NOT_SUPPORTED ,PROPAGATION_REQUIRES_NEW )。ui
上面提了一下七種傳播行爲的含義,可是隻看這個彷佛有一點摸不着頭腦,我我的認爲傳播行爲的存在是爲了解決各個事務方法之間調用可能出現的問題,(這裏就涉及理念對實際可能出現的狀況作的一種抽象)。 spa
舉一兩個例子:傳播行爲「PROPAGATION_MANDATORY 」這個行爲的意思就調用該方法的方法必須是一個事務方法(有點繞),不少時候咱們對那些很是重要的數據進行刪除,修改,增長的時候咱們確定但願他們的處於事務中,改到一半失敗了,這個是超級可怕的事情。這個傳播行爲的價值就體現出來了,保證了調用該行爲的方法都是事務方法。還有"PROPAGATION_NEVER ",不容許事務方法調用該方法,由於咱們知道事務方法通常是有時間限制的,像一些超級耗時間的方法,咱們給他加上這個傳播行爲,就能夠提醒事務方法不要再使用這個了(不知足特殊狀況哈)。code
上面只是提到一些理念對實際的抽象,傳播行爲之間最奇特的仍是傳播行爲之間的組合能夠解決不少實際上容易面臨的問題。
xml
例如:下面舉的例子都要關注事務邊界哈:事務
PROPAGATION_REQUIRED and PROPAGATION_REQUIRED 傳播行爲的組合ci
@Transactional(propagation=Propagation.REQUIRED ,rollbackFor=AcceptPendingException.class) public void testRequiredAndRequired(){ //事務開頭 insertInfo1();//包含在了testRequiredAndRequired裏面 insertInfo2();//包含在了testRequiredAndRequired裏面 //事務結束 } @Transactional(propagation=Propagation.REQUIRED) public void insertInfo1(){ ud.insert(10); // throw new AcceptPendingException(); } @Transactional(propagation=Propagation.REQUIRED) public void insertInfo2(){ ud.insert(11); throw new AbstractMethodError(); } public static void main(String args[]) { ApplicationContext ac = new ClassPathXmlApplicationContext( "com/springinaction/springidol/spring-tx.xml"); UserService us = (UserService) ac.getBean("userService"); us.testRequiredAndRequired(); }
發現傳播行爲:PROPAGATION_REQUIRED 事務邊界內只要拋出異常,結果都會回滾。get
通過測試發現:PROPAGATION_REQUIRES_NEW 傳播行爲是在DataSourceTransactionManager 中不支持的,和PROPAGATION_REQUIRED 行爲是相同的。
PROPAGATION_REQUIRED and Propagation.SUPPORTS 傳播行爲的組合
@Transactional(propagation = Propagation.REQUIRED,readOnly = false, rollbackFor = AcceptPendingException.class) public void testRquiredAndSupported(){ //事務開始 insertInfo1(); insertInfo2(); //事務結束 } @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = AcceptPendingException.class) public void insertInfo1() { ud.insert(10); throw new AcceptPendingException(); } // @Transactional(propagation = Propagation.REQUIRES_NEW) public void insertInfo2() { ud.insertAccount(11); // throw new AbstractMethodError(); } public static void main(String args[]) { ApplicationContext ac = new ClassPathXmlApplicationContext( "com/springinaction/springidol/spring-tx.xml"); UserService us = (UserService) ac.getBean("userService"); us.insertInfo1(); }
當只有Propagation.SUPPORTS 轉播行爲的時候是沒有事務邊界的。當PROPAGATION_REQUIRED 下的SUPPORTS 的時候這個時候事務邊界就是當前方法的事務邊界。
可見咱們使用傳播行爲的時候主要就是關注事務的邊界。就和能夠很好的使用傳播行爲了。