事務管理對于企業應用來說是至關重要的,即使出現異常情況,它也可以保證資料的一緻性。
spring支援程式設計式事務管理(基本不用,忽略)和聲明式事務管理兩種方式。
聲明式事務管理也有兩種常用的方式,一種是基于tx和aop名字空間的xml配置檔案,另一種就是基于@Transactional注解。顯然基于注解的方式更簡單易用,更清爽。此處就說明一下注解的用法:
事務注解方式: @Transactional
[email protected]屬性
屬性 | 類型 | 描述 |
---|---|---|
value | String | 可選的限定描述符,指定使用的事務管理器 |
propagation | enum: Propagation | 可選的事務傳播行為設定 |
isolation | enum: Isolation | 可選的事務隔離級别設定 |
readOnly | boolean | 讀寫或隻讀事務,預設讀寫 |
timeout | int (in seconds granularity) | 事務逾時時間設定 |
rollbackFor | Class對象數組,必須繼承自Throwable | 導緻事務復原的異常類數組 |
rollbackForClassName | 類名數組,必須繼承自Throwable | 導緻事務復原的異常類名字數組 |
noRollbackFor | Class對象數組,必須繼承自Throwable | 不會導緻事務復原的異常類數組 |
noRollbackForClassName | 類名數組,必須繼承自Throwable | 不會導緻事務復原的異常類名字數組 |
2.事物傳播行為
@Transactional(propagation=Propagation.REQUIRED)
如果有事務, 那麼加入事務, 沒有的話建立一個(預設情況下)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
容器不為這個方法開啟事務
@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事務,都建立一個新的事務,原來的挂起,新的執行完畢,繼續執行老的事務
@Transactional(propagation=Propagation.MANDATORY)
必須在一個已有的事務中執行,否則抛出異常
@Transactional(propagation=Propagation.NEVER)
必須在一個沒有的事務中執行,否則抛出異常(與Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS)
如果其他bean調用這個方法,在其他bean中聲明事務,那就用事務.如果其他bean沒有聲明事務,那就不用事務.
3.事務隔離級别
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
讀取未送出資料(會出現髒讀, 不可重複讀) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)
讀取已送出資料(會出現不可重複讀和幻讀)
@Transactional(isolation = Isolation.REPEATABLE_READ)
可重複讀(會出現幻讀)
@Transactional(isolation = Isolation.SERIALIZABLE)
4.事物逾時
所謂事務逾時,就是指一個事務所允許執行的最長時間,如果超過該時間限制但事務還沒有完成,則自動復原事務。在 TransactionDefinition 中以 int 的值來表示逾時時間,其機關是秒。
預設設定為底層事務系統的逾時值,如果底層資料庫事務系統沒有設定逾時值,那麼就是none,沒有逾時限制
逾時設定
@Transactional(timeout=30) //預設是30秒
5.事務隻讀屬性
隻讀事務用于客戶代碼隻讀但不修改資料的情形,隻讀事務用于特定情景下的優化,比如使用Hibernate的時候。
預設為讀寫事務。
spring事務復原規則
訓示spring事務管理器復原一個事務的推薦方法是在目前事務的上下文内抛出異常。spring事務管理器會捕捉任何未處理的異常,然後依據規則決定是否復原抛出異常的事務。
預設配置下,spring隻有在抛出的異常為運作時unchecked異常時才復原該事務,也就是抛出的異常為RuntimeException的子類(Errors也會導緻事務復原),而抛出checked異常則不會導緻事務復原。
可以明确的配置在抛出那些異常時復原事務,包括checked異常。也可以明确定義那些異常抛出時不復原事務。
注解有有兩種方式:
第一種在實體類上,當作用于類上時,該類的所有 public 方法将都具有該類型的事務屬性,同時,我們也可以在方法級别使用該标注來覆寫類級别的定義。
@Transactional
public class TestServiceBean implements TestService {}
當某個方法不需要注解時
@Transactional
public class TestServiceBean implements TestService {
private TestDao dao;
public void setDao(TestDao dao) {
this.dao = dao;
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public List<Object> getAll() {
return null;
}
}
第二種方式在方法上,針對某個方法開啟事務的管理
public class TestServiceBean implements TestService {
private TestDao dao;
public void setDao(TestDao dao) {
this.dao = dao;
}
@Transactional
public List<Object> getAll() {
return null;
}
}
注意事項:
@Transactional 可以作用于接口、接口方法、類以及類方法上。當作用于類上時,該類的所有 public 方法将都具有該類型的事務屬性,同時,我們也可以在方法級别使用該标注來覆寫類級别的定義。
雖然 @Transactional 注解可以作用于接口、接口方法、類以及類方法上,但是 Spring 建議不要在接口或者接口方法上使用該注解,因為這隻有在使用基于接口的代理時它才會生效。另外, @Transactional 注解應該隻被應用到 public 方法上,這是由 Spring AOP 的本質決定的。如果你在 protected、private 或者預設可見性的方法上使用 @Transactional 注解,這将被忽略,也不會抛出任何異常。
在項目中,@Transactional(rollbackFor=Exception.class),如果類加了這個注解,那麼這個類裡面的方法抛出異常,就會復原,資料庫裡面的資料也會復原。
在@Transactional注解中如果不配置rollbackFor屬性,那麼事物隻會在遇到RuntimeException的時候才會復原(errors預設也會復原),加上rollbackFor=Exception.class,可以讓事物在遇到非運作時異常時也復原。
擴充:異常知識
異常的繼承結構:Throwable為基類,Error和Exception繼承Throwable,RuntimeException和IOException等繼承Exception。Error和RuntimeException及其子類成為未檢查異常(unchecked),其它異常成為已檢查異常(checked)。

這裡Exception是異常,又分為運作時異常(RuntimeException)和非運作時異常。
運作時異常:RuntimeException及其子類。如果不對運作時異常進行處理,那麼出現運作時異常之後,要麼是線程中止,要麼是主程式終止。 如果不想終止,則必須捕獲所有的運作時異常,決不讓這個處理線程退出。隊列裡面出現異常資料了,正常的處理應該是把異常資料舍棄,然後記錄日志。不應該由于異常資料而影響下面對正常資料的處理。
非運作時異常:RuntimeException以外的異常,類型上都屬于Exception類及其子類,如IOException、SQLException等以及使用者自定義的Exception異常。對于這種異常,JAVA編譯器強制要求我們必需對出現的這些異常進行catch并處理,否則程式就不能編譯通過。是以,面對這種異常不管我們是否願意,隻能自己去寫一大堆catch塊去處理可能的異常。
以上内容是本人結合網上多篇文章進行了歸納和總結,如有寫的不對的地方請指出!