spring中的事務管理機制


1. Spring事務管理機制
  1)編程式事務管理(不常用)
    所謂編程式事務指的是通過編碼方式實現事務,即類似於JDBC編程實現事務管理。

  2)聲明式事務管理(常用)
    在Spring配置文件中聲明式的處理事務來代替代碼式的處理事務.
    在spring中,聲明式事務主要是通過【事務屬性】來定義的,事務屬性描述了事務策略如何應用到方法上面

2.事務屬性主要包含了以下5個方面:(文檔的最后有統一的介紹)
  傳播行為 隔離級別 回滾規則 事務超時 是否只讀

     傳播行為 (propagation):

  規定了如果有新的事務應該被啟動還是被掛起,或者方法是否需要在事務中運行。
      

   隔離級別 (isolation):

  定義了一個事務可能受其他並發事務影響的程度。


        回滾規則 (rollback-for no-rollback-for):

  定義了哪些異常會導致事務回滾而哪些不會。


        事務超時 (timeout):

  事務不能運行太長的時間,所以這個屬性就控制着這個時間.


        是否只讀 (read-only):

  定義了一個事務中是否是只讀操作

聲明式事務管理的配置方式通常以下幾種:
注意:配置事務的方式都需要用到事務管理器(切面)和事務攔截器(advice),其實就是使用aop編程,把事務代碼動態織入到需要使用的方法上


了解事務屬性包含的五個方面分別是什么:

1)事務傳播行為
  規定了如果有新的事務應該被啟動還是被掛起,或者方法是否需要在事務中運行。

  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。

 

name 是必須的,表示與事務屬性關聯的方法名(業務方法名),對切入點進行細化。通配符(*)可以用來指定一批關聯到相同的事務屬性的方法。
如:'get*'、'handle*'、'on*Event'等等

2)事務隔離級別
  定義了一個事務可能受其他並發事務影響的程度。
隔離級別是指若干個並發的事務之間的隔離程度。TransactionDefinition 接口中定義了五個表示隔離級別的常量:
  臟讀(沒提交的數據),不可重復讀(讀到了提交的(update,d)),幻讀(讀到了提交的,insert)

TransactionDefinition.ISOLATION_DEFAULT:這是默認值,表示使用底層數據庫的默認隔離級別。對大部分數據庫而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED。

TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級別表示一個事務可以讀取另一個事務修改但還沒有提交的數據。該級別不能防止臟讀和不可重復讀,因此很少使用該隔離級別。
TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級別表示一個事務只能讀取另一個事務已經提交的數據。該級別可以防止臟讀,這也是大多數情況下的推薦值。
TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級別表示在同一事務中,同一查詢多次進行時候,由於其他插入操作(insert)的事務提交,導致每次返回不同的結果集。該級別可以防止臟讀和不可重復讀。
TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。

注意:不同的數據庫所能支持的事務隔離級別以及默認的事務隔離級別有可能是不同的,不同的隔離級別有不同的現象,並有不同的並發機制,隔離級別越高,數據庫的並發性就越差。

3)事務的只讀屬性
定義了一個事務中是否是只讀操作,如果設置只讀那么數據庫內部就可以對該操作進行合適的優化措施,只有傳播行為是PROPAGATION_REQUIRED PROPAGATION_REQUIRES_NEW PROPAGATION_NESTED的時候只讀設置才有意義,因為只讀優化是在事務開始的時候由數據庫實施的,而在這三個傳播行為下才有可能啟動一個新事務
find*,get*[優化]:開啟*提交,不寫
“只讀事務”並不是一個強制選項,它只是一個“暗示”,提示數據庫驅動程序和數據庫系統,這個事務並不包含更改數據的操作,那么JDBC驅動程序和數據庫就有可能根據這種情況對該事務進行一些特定的優化,比方說不安排相應的數據庫鎖,以減輕事務對數據庫的壓力,畢竟事務也是要消耗數據庫的資源的。

4)事務超時
為了使應用程序可以很好的運行,事務不能運行太長的時間,所以這個屬性就控制着這個時間.只有傳播行為是PROPAGATION_REQUIRED PROPAGATION_REQUIRES_NEW PROPAGATION_NESTED的時候超時設置才有意義,因為超時時鍾會在事務開始的時候啟動,而在這三個傳播行為下才有可能啟動一個新事務.注意事務超時后會自動回滾.(單位是 秒),默認值-1(永不超時)

5)事務的回滾規則
定義了哪些異常會導致事務回滾而哪些不會。默認情況下,事務在遇到運行時異常的時候才會回滾,而遇到檢查時異常時不會回滾
-Exception表示有Exception拋出時,事務回滾. -代表回滾+就代表提交

 

<!-- tx:method的屬性:
* name 是必須的,表示與事務屬性關聯的方法名(業務方法名),對切入點進行細化。通配符(*)可以用來指定一批關聯到相同的事務屬性的方法。
如:'get*'、'handle*'、'on*Event'等等.
* propagation 不是必須的 ,默認值是REQUIRED
表示事務傳播行為, 包括REQUIRED,SUPPORTS,MANDATORY,REQUIRES_NEW,NOT_SUPPORTED,NEVER,NESTED
* isolation 不是必須的 默認值DEFAULT
表示事務隔離級別(數據庫的隔離級別)
* timeout 不是必須的 默認值-1(永不超時)
表示事務超時的時間(以秒為單位)
* read-only 不是必須的 默認值false不是只讀的
表示事務是否只讀?
* rollback-for 不是必須的
表示將被觸發進行回滾的 Exception(s);以逗號分開。
* no-rollback-for 不是必須的
表示不被觸發進行回滾的 Exception(s);以逗號分開。

-->

//測試默認情況下
// throw new Exception("默認配置下,發生checkException異常是否回滾,不回滾");
// throw new SQLException("默認配置下,發生checkException異常是否回滾,不回滾");
// throw new Error("默認配置下,發生uncheckException異常是否回滾,回滾");
// throw new RuntimeException("默認配置下,發生uncheckException異常是否回滾,回滾");

/*try {
// throw new SQLException("默認配置下,捕獲checkException異常是否回滾,不回滾");
// throw new Exception("默認配置下,捕獲checkException異常是否回滾,不回滾");
// throw new Error("默認配置下,捕獲uncheckException異常是否回滾,不回滾");
// throw new RuntimeException("默認配置下,捕獲uncheckException異常是否回滾,不回滾");
} catch (Exception e) {
e.printStackTrace();
}*/

//檢測配置rollback-for="Throwable"下
// throw new Exception("配置Throwable下,發生checkException異常是否回滾,回滾");
// throw new SQLException("配置Throwable下,發生checkException異常是否回滾,回滾");
// throw new Error("配置Throwable下,發生uncheckException異常是否回滾,回滾");
// throw new RuntimeException("配置Throwable下,發生uncheckException異常是否回滾,回滾");
/*try {
// throw new Exception("配置Throwable下,發生checkException異常是否回滾,不回滾");
// throw new SQLException("配置Throwable下,發生checkException異常是否回滾,不回滾");
// throw new Error("配置Throwable下,發生uncheckException異常是否回滾,不回滾");
// throw new RuntimeException("配置Throwable下,發生uncheckException異常是否回滾,不回滾");
} catch (Exception e) {
e.printStackTrace();
}*/
//結論:拋異常的情況下,默認只回滾uncheck異常(runtime和error),經過配置Throwable后,子類異常和錯誤都回滾
// 但是try/catch后,全部不回滾


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM