首頁 >Java >java教程 >詳細介紹Spring中@Transactional事務回滾實例及原始碼(圖)

詳細介紹Spring中@Transactional事務回滾實例及原始碼(圖)

黄舟
黄舟原創
2017-03-30 11:00:592127瀏覽

一、使用場景舉例

在了解@Transactional怎麼用之前我們必須先知道@Transactional有什麼用。下面舉個栗子:例如一個部門裡面有很多成員,這兩者分別保存在部門表和成員表裡面,在刪除某個部門的時候,假設我們預設刪除對應的成員。但是在執行的時候可能會出現這種情況,我們先刪除部門,再刪除成員,但是部門刪除成功了,刪除成員的時候出異常了。這時候我們希望如果成員刪除失敗了,先前刪除的部門也取消刪除。這種場景就可以使用@Transactional事物回滾。

二、checked異常和unchecked異常

這裡之所以讓大家清楚checked異常和unchecked異常概念,是因為:

Spring使用聲明式事務處理,預設情況下,如果被註解的資料庫操作方法中發生了unchecked異常,所有的資料庫操作將rollback;如果發生的異常是checked異常,預設情況下資料庫操作還是會提交的。

checked例外:

表示無效,不是程式中可以預測的。例如無效的使用者輸入,檔案不存在,網路或資料庫連結錯誤。這些都是外在的原因,都不是程式內部可以控制的。

必須在程式碼中明確地處理。例如try-catch區塊處理,或是給所在的方法加上throws說明,將異常拋到呼叫棧的上一層。

繼承自java.lang.Exception(java.lang.RuntimeException除外)。

unchecked異常:

表示錯誤,程式的邏輯錯誤。是RuntimeException的子類,例如IllegalArgumentException, NullPointerException和IllegalStateException。

不需要在程式碼中明確地捕獲unchecked異常做處理。

繼承自java.lang.RuntimeException(而java.lang.RuntimeException繼承自java.lang.Exception)。

看下面的異常結構圖或許層次感更加深些:

詳細介紹Spring中@Transactional事務回滾實例及原始碼(圖)

#三、@Transactional的使用實例

本實例採用的是Eclipse+maven,maven只是作為jar管理,即使不了解的maven的猿友也可以讀懂。

3.1、spring的設定檔

裡面必須先設定tx名字空間如下:

詳細介紹Spring中@Transactional事務回滾實例及原始碼(圖)

為了使用基於@Transactional的事務管理,需要在Spring中進行如下的配置:

<bean id="appTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven proxy-target-class="false" transaction-manager="appTransactionManager" />

博主的整個spring設定檔:




       
     
        
            
               classpath:properties/*.properties
                
            
        
    

    
    
        
        
       
        
            ${jdbc_driverClassName}
        
        
            ${jdbc_url}
        
        
            ${jdbc_username}
        
        
            ${jdbc_password}
        
    

    <bean id="appTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven proxy-target-class="false" transaction-manager="appTransactionManager" />

    
    
        
    

    
    
        
          
        
        
    

    
    

3.2、使用@Transactional,在新增使用者實作類別方法加上註解

@Transactional(propagation=Propagation.REQUIRED)
public void addUser(User user) {
    userDao.addUser(user);
    String string  = null;
    if(string.equals("")) {
        int i = 0;
    }
}

上面的方法我故意讓其出現空指標異常,會事物回滾

3.3、運行單元測試類別

@Test  
public void addUserTest(){  
    User user = new User();
    user.setUserName("luoguohui1");
    user.setUserPassword("luoguohui1");
    userService.addUser(user);
}

發現無法插入進去,但是如果把@Transactional去掉,即程式碼如下,雖然出現異常,但是資料庫中還是有新增對應資料的:

詳細介紹Spring中@Transactional事務回滾實例及原始碼(圖)

3.4、原始碼下載

本文的工程是在mybatis入門(含實例教學與原始碼)的基礎上修改的,該文包含了資料庫腳本及工程搭建的詳細流程。

四、Spring中的@Transactional必須要了解的概念

Spring中的@Transactional基於動態代理的機制,提供了一種透明的事務管理機制,方便快捷解決在開發中碰到的問題。

一般使用是透過以下程式碼對方法或介面或類別註解

@Transactional(propagation=Propagation.NOT_SUPPORTED)

Propagation支援7種不同的傳播機制:

REQUIRED:如果存在一個事務,則支援目前事務。如果沒有事務則開啟一個新的事務。

SUPPORTS: 如果存在一個事務,支援目前事務。如果沒有事務,則非事務的執行。但是對於交易同步的事務管理器,PROPAGATION_SUPPORTS與不使用交易有少許不同。

NOT_SUPPORTED:總是非交易地執行,並掛起任何存在的交易。

REQUIRESNEW:總是開啟一個新的交易。如果一個事務已經存在,則將這個存在的事務掛起。

MANDATORY:如果已經存在一個事務,支援目前事務。如果沒有一個活動的事務,則拋出異常

NEVER:總是非事務地執行,如果存在一個活動事務,則拋出異常

NESTED:如果一個活動的事務存在,則運行在一個嵌套的事務中。如果沒有活動事務,則按REQUIRED屬性執行。

以下是一些需要注意的事項,必須必須要看,不然遇到各種坑別說博主沒有提醒你哦

##以下是一些需要注意的事項,必須必須要看,不然遇到各種坑別說博主沒有提醒你哦

下面是一些需要注意的事項,必須必須必須要看,不然遇到各種坑別說博主沒有提醒你哦

  • #在需要事務管理的地方加@Transactional 註解。 @Transactional 註解可以被套用在介面定義和介面方法、類別定義和類別的 public 方法上。

  • @Transactional 註解只能應用在 public 可見度的方法。 如果你在 protected、private 或 package-visible 的方法上使用 @Transactional 註解,它也不會報錯, 但是這個被註解的方法將不會顯示已設定的事務設定。

  • 注意僅僅 @Transactional 註解的出現不足於開啟事務

    行為,它只是一種元資料。必須在設定檔中使用配置元素,才真正開啟了事務行為。

  • 透過 元素的 “proxy-target-class” 屬性值來控制是基於介面的還是基於類別的代理程式被建立。如果 “proxy-target-class” 屬值被設定為 “true”,那麼基於類別的代理就會起作用(這時需要CGLIB函式庫cglib.jar在CLASSPATH中)。如果 “proxy-target-class” 屬值被設定為 “false” 或這個屬性被省略,那麼標準的JDK基於介面的代理就會起作用。

  • Spring團隊建議在特定的類別(或類別的方法)上使用 @Transactional 註解,而不要使用在類別所要實作的任何介面上。在介面上使用 @Transactional 註解,只能當你設定了基於介面的代理程式時它才生效。因為註解是不能繼承的,這就意味著如果正在使用基於類別的代理時,那麼事務的設定將不能被基於類別的代理所識別,而且

    物件也將不會被事務代理所包裝。

  • @Transactional 的事務開啟 ,或是基於介面的 或是基於類別的代理程式被建立。所以在同一個類別中一個方法呼叫另一個方法有事務的方法,事務是不會起作用的。

  • #

以上是詳細介紹Spring中@Transactional事務回滾實例及原始碼(圖)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn