事務相關的知識

事務的特性:

原子性:事務是不可分割的最小單元,事務裏的操作要麼都做要麼都不做

隔離性:在併發程序中,併發事務之間互不影響,在對一個事務的操作不會對其他事務產生影響,事務的隔離性需要事務的隔離級別來完成。

一致性:在事務執行前後數據庫的數據都處於正確的狀態,

持久性:事務一旦執行成功,那麼對數據庫數據的改變是永久的,不會因爲因爲斷點或者系統故障而發生數據丟失。

 

在實際項目開發中,事務一般都是併發執行的,事務併發執行一般會遇到以下問題:

丟失更新:兩個事務先後更新同一行數據,後執行的事務的更新覆蓋掉了前一個事務的更新,這樣會導致前一個事務更新的數據丟失,這是由於沒有加鎖造成的。

髒讀:一個事務看到了另一個事務未提交的更新的數據。

不可重複讀:在同一事物中,多次讀取同一條數據確返回不同的結果。因爲有其他的事務更改了這些數據。

幻讀:一個事務在執行過程中讀取到了另一個事務已提交的插入數據,即第一個事務開始時讀取到一批數據,此時另一個事務又插入數據並提交,然後第一個事務又讀取這批數據單發現多了一條。

 

爲了解決事務併發的問題,規定了四種隔離級別:

1.未提交讀:最低的隔離級別,一個事務能夠讀取到別的事務未提交的更新數據,這很不安全,可能會導致丟失更新,髒讀,不可重複讀,幻讀。

2.提交讀:一個事務能讀取到別的事務提交的更新數據,不能看到未提交的更新數據,這樣避免了丟失更新,但是肯能會產生髒讀、不可重複讀、幻讀。

3.可重複讀:保證同一個事務中先後執行多次查詢都返回同一個結果,不受其他事務的影響,解決了丟失更新、髒讀、不可重複讀的問題,但是可能產生幻讀。

4.序列化:最高隔離級別,不允許事務併發執行,只能串行執行,避免了,丟失更新、髒讀、不可重複讀、幻讀等問題。

 

spring中對事務的支持分爲物理事物和邏輯事務。

物理事物就是底層數據庫提供的事務支持,例如JDBC

邏輯事務是spring管理的事務,邏輯事務提供更豐富的控制,在spring中如果沒有強調一般就是邏輯事務。

 

DefaultTransactionDefinition:事務定義,定義如隔離級別、傳播行爲,事務超時時間,事務是否只讀等。

 

例如:

  1.  DefaultTransactionDefinition def = new DefaultTransactionDefinition();  
  2.     def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
  3.     def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 

 

定義事務的隔離級別爲提交讀,傳播行爲爲必須有事務,如果沒有事務則創建一個事務。

TransactionStatus:表示事務的狀態,獲取事務狀態後,spring根據事務的傳播行爲開啓事務。

 

事務隔離級別

spring 中使用TransactionDefinition的靜態變量來制定事務的隔離級別:

ISOLATION_DEFAULT:默認的隔離級別,使用底層的數據庫的默認的隔離級別。

IOSLATION_READ_UNCOMMITED:未提交讀

ISOLATION_READ_COMMITED:提交讀

IOSLATION_REPEATABLE_READ:可重複讀

IOSLATION_SERIALIZABLE:序列化

 

事務的傳播行爲:

事務的傳播行爲指定在多個事務方法間調用時,事務是如何在這些方法間傳播的。

spring共支持7種事務傳播行爲:

1.reuqired:必須有事務,否則新建一個事務,使用PROPAGATION_REQUIRED指定。

2.requiresNew:表示每次都創建新的邏輯事務,使用PROPAGATION_REQUIRES_NEW指定。

3.Supports:支持當前事務,使用PROPAGATION_SUPPORTS指定,如果當前存在邏輯事務,就加入到該邏輯事務中,如果當前沒有邏輯事務就以非邏輯事務的方式運行。

4.NotSupported:不支持事務,如果當前存在事務,則暫停該事物,以非事務的方式運行,使用PROPAGATION_NOT_SUPPORTED指定

5.Mandatory:使用當前事務執行,如果當前沒有事務則拋出異常,用PROPAGATION_MANDATORY指定

6.NEVER:不支持事務,如果當前存在事務則拋出異常,使用PROGATION_NEVER指定。

7.NESTED:嵌套事務支持,如果當前存在事務,則在嵌套事務內執行,如果當前事務不存在,則創建新的事務。嵌套事務使用數據庫中的保存點來執行,即嵌套事務回滾將不影響外部事務,外部事務回滾將導致嵌套事務回滾。

 

  1. <tx:advice id="txAdvice" transaction-manager="txManager">  
  2. <tx:attributes>  
  3.            <tx:method name="save*" propagation="REQUIRED" />  
  4.            <tx:method name="add*" propagation="REQUIRED" />  
  5.            <tx:method name="create*" propagation="REQUIRED" />  
  6.            <tx:method name="insert*" propagation="REQUIRED" />  
  7.            <tx:method name="update*" propagation="REQUIRED" />  
  8.            <tx:method name="merge*" propagation="REQUIRED" />  
  9.            <tx:method name="del*" propagation="REQUIRED" />  
  10.            <tx:method name="remove*" propagation="REQUIRED" />  
  11.            <tx:method name="put*" propagation="REQUIRED" />  
  12.            <tx:method name="get*" propagation="SUPPORTS" read-only="true" />  
  13.            <tx:method name="count*" propagation="SUPPORTS" read-only="true" />  
  14.           <tx:method name="find*" propagation="SUPPORTS" read-only="true" />  
  15.           <tx:method name="list*" propagation="SUPPORTS" read-only="true" />  
  16.           <tx:method name="*" propagation="SUPPORTS" read-only="true" />  
  17.        </tx:attributes>  
  18. </tx:advice>  

 

 

 註解式事務聲明:

 

  @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED)

    @Override

    public void save(final UserModel user) {

        userDao.save(user);

        user.getAddress().setUserId(user.getId());

        addressService.save(user.getAddress());

        

    }

 

    @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, readOnly=true)

    @Override

    public int countAll() {

        return userDao.countAll();

    }

 

 

 

 

發佈了55 篇原創文章 · 獲贊 5 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章