欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

spring的@Transactional注解用法解讀

 更新時間:2018年01月02日 09:20:55   作者:一人淺醉-  
這篇文章主要介紹了spring的@Transactional注解用法解讀,具有一定借鑒價值,需要的朋友可以參考下

概述

事務(wù)管理對于企業(yè)應(yīng)用來說是至關(guān)重要的,即使出現(xiàn)異常情況,它也可以保證數(shù)據(jù)的一致性。

Spring Framework對事務(wù)管理提供了一致的抽象,其特點如下:

為不同的事務(wù)API提供一致的編程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)

支持聲明式事務(wù)管理,特別是基于注解的聲明式事務(wù)管理,簡單易用

提供比其他事務(wù)API如JTA更簡單的編程式事務(wù)管理API

與spring數(shù)據(jù)訪問抽象的完美集成

事務(wù)管理方式

spring支持編程式事務(wù)管理和聲明式事務(wù)管理兩種方式。

編程式事務(wù)管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對于編程式事務(wù)管理,spring推薦使用TransactionTemplate。

聲明式事務(wù)管理建立在AOP之上的。其本質(zhì)是對方法前后進(jìn)行攔截,然后在目標(biāo)方法開始之前創(chuàng)建或者加入一個事務(wù),在執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行情況提交或者回滾事務(wù)。聲明式事務(wù)最大的優(yōu)點就是不需要通過編程的方式管理事務(wù),這樣就不需要在業(yè)務(wù)邏輯代碼中摻雜事務(wù)管理的代碼,只需在配置文件中做相關(guān)的事務(wù)規(guī)則聲明(或通過基于@Transactional注解的方式),便可以將事務(wù)規(guī)則應(yīng)用到業(yè)務(wù)邏輯中。

顯然聲明式事務(wù)管理要優(yōu)于編程式事務(wù)管理,這正是spring倡導(dǎo)的非侵入式的開發(fā)方式。聲明式事務(wù)管理使業(yè)務(wù)代碼不受污染,一個普通的POJO對象,只要加上注解就可以獲得完全的事務(wù)支持。和編程式事務(wù)相比,聲明式事務(wù)唯一不足地方是,后者的最細(xì)粒度只能作用到方法級別,無法做到像編程式事務(wù)那樣可以作用到代碼塊級別。但是即便有這樣的需求,也存在很多變通的方法,比如,可以將需要進(jìn)行事務(wù)管理的代碼塊獨立為方法等等。

聲明式事務(wù)管理也有兩種常用的方式,一種是基于tx和aop名字空間的xml配置文件,另一種就是基于@Transactional注解。顯然基于注解的方式更簡單易用,更清爽。

自動提交(AutoCommit)與連接關(guān)閉時的是否自動提交

自動提交

默認(rèn)情況下,數(shù)據(jù)庫處于自動提交模式。每一條語句處于一個單獨的事務(wù)中,在這條語句執(zhí)行完畢時,如果執(zhí)行成功則隱式的提交事務(wù),如果

執(zhí)行失敗則隱式的回滾事務(wù)。

對于正常的事務(wù)管理,是一組相關(guān)的操作處于一個事務(wù)之中,因此必須關(guān)閉數(shù)據(jù)庫的自動提交模式。不過,這個我們不用擔(dān)心,spring會將底層連接的自動提交特性設(shè)置為false。

org/springframework/jdbc/datasource/DataSourceTransactionManager.java

// switch to manual commit if necessary. this is very expensive in some jdbc drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
if (con.getautocommit()) {
  txobject.setmustrestoreautocommit(true);
  if (logger.isdebugenabled()) {
    logger.debug("switching jdbc connection [" + con + "] to manual commit");
  }
  con.setautocommit(false);
}

有些數(shù)據(jù)連接池提供了關(guān)閉事務(wù)自動提交的設(shè)置,最好在設(shè)置連接池時就將其關(guān)閉。但C3P0沒有提供這一特性,只能依靠spring來設(shè)置。

因為JDBC規(guī)范規(guī)定,當(dāng)連接對象建立時應(yīng)該處于自動提交模式,這是跨DBMS的缺省值,如果需要,必須顯式的關(guān)閉自動提交。C3P0遵守這一規(guī)范,讓客戶代碼來顯式的設(shè)置需要的提交模式。

連接關(guān)閉時的是否自動提交

當(dāng)一個連接關(guān)閉時,如果有未提交的事務(wù)應(yīng)該如何處理?JDBC規(guī)范沒有提及,C3P0默認(rèn)的策略是回滾任何未提交的事務(wù)。這是一個正確的策略,但JDBC驅(qū)動提供商之間對此問題并沒有達(dá)成一致。

C3P0的autoCommitOnClose屬性默認(rèn)是false,沒有十分必要不要動它?;蛘呖梢燥@式的設(shè)置此屬性為false,這樣會更明確。

基于注解的聲明式事務(wù)管理配置

spring-servlet.xml

<!-- transaction support-->
<!-- PlatformTransactionMnager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource" />
</bean>
<!-- enable transaction annotation support -->
<tx:annotation-driven transaction-manager="txManager" />

還要在spring-servlet.xml中添加tx名字空間

...
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xsi:schemaLocation="
  ...
http://www.springframework.org/schema/tx
 
http://www.springframework.org/schema/tx/spring-tx.xsd
  ...

MyBatis自動參與到spring事務(wù)管理中,無需額外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的數(shù)據(jù)源與DataSourceTransactionManager引用的數(shù)據(jù)源一致即可,否則事務(wù)管理會不起作用。

另外需要下載依賴包aopalliance.jar放置到WEB-INF/lib目錄下。否則spring初始化時會報異常

java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor

spring事務(wù)特性

spring所有的事務(wù)管理策略類都繼承自org.springframework.transaction.PlatformTransactionManager接口

public interface PlatformTransactionManager {
	TransactionStatus getTransaction(TransactionDefinition definition)
	  throws TransactionException;
	void commit(TransactionStatus status) throws TransactionException;
	void rollback(TransactionStatus status) throws TransactionException;
}

其中TransactionDefinition接口定義以下特性:

事務(wù)隔離級別

隔離級別是指若干個并發(fā)的事務(wù)之間的隔離程度。TransactionDefinition 接口中定義了五個表示隔離級別的常量:

TransactionDefinition.ISOLATION_DEFAULT:這是默認(rèn)值,表示使用底層數(shù)據(jù)庫的默認(rèn)隔離級別。對大部分?jǐn)?shù)據(jù)庫而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED。

TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級別表示一個事務(wù)可以讀取另一個事務(wù)修改但還沒有提交的數(shù)據(jù)。該級別不能防止臟讀,不可重復(fù)讀和幻讀,因此很少使用該隔離級別。比如PostgreSQL實際上并沒有此級別。

TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級別表示一個事務(wù)只能讀取另一個事務(wù)已經(jīng)提交的數(shù)據(jù)。該級別可以防止臟讀,這也是大多數(shù)情況下的推薦值。

TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級別表示一個事務(wù)在整個過程中可以多次重復(fù)執(zhí)行某個查詢,并且每次返回的記錄都相同。該級別可以防止臟讀和不可重復(fù)讀。

TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務(wù)依次逐個執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾,也就是說,該級別可以防止臟讀、不可重復(fù)讀以及幻讀。但是這將嚴(yán)重影響程序的性能。通常情況下也不會用到該級別。

事務(wù)傳播行為

所謂事務(wù)的傳播行為是指,如果在開始當(dāng)前事務(wù)之前,一個事務(wù)上下文已經(jīng)存在,此時有若干選項可以指定一個事務(wù)性方法的執(zhí)行行為。在TransactionDefinition定義中包括了如下幾個表示傳播行為的常量:

TransactionDefinition.PROPAGATION_REQUIRED:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個新的事務(wù)。這是默認(rèn)值。

TransactionDefinition.PROPAGATION_REQUIRES_NEW:創(chuàng)建一個新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。

TransactionDefinition.PROPAGATION_SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運行。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。

TransactionDefinition.PROPAGATION_NEVER:以非事務(wù)方式運行,如果當(dāng)前存在事務(wù),則拋出異常。

TransactionDefinition.PROPAGATION_MANDATORY:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。

TransactionDefinition.PROPAGATION_NESTED:如果當(dāng)前存在事務(wù),則創(chuàng)建一個事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運行;如果當(dāng)前沒有事務(wù),則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED。

事務(wù)超時

所謂事務(wù)超時,就是指一個事務(wù)所允許執(zhí)行的最長時間,如果超過該時間限制但事務(wù)還沒有完成,則自動回滾事務(wù)。在 TransactionDefinition 中以 int 的值來表示超時時間,其單位是秒。

默認(rèn)設(shè)置為底層事務(wù)系統(tǒng)的超時值,如果底層數(shù)據(jù)庫事務(wù)系統(tǒng)沒有設(shè)置超時值,那么就是none,沒有超時限制。

事務(wù)只讀屬性

只讀事務(wù)用于客戶代碼只讀但不修改數(shù)據(jù)的情形,只讀事務(wù)用于特定情景下的優(yōu)化,比如使用Hibernate的時候。

默認(rèn)為讀寫事務(wù)。

spring事務(wù)回滾規(guī)則

指示spring事務(wù)管理器回滾一個事務(wù)的推薦方法是在當(dāng)前事務(wù)的上下文內(nèi)拋出異常。spring事務(wù)管理器會捕捉任何未處理的異常,然后依據(jù)規(guī)則決定是否回滾拋出異常的事務(wù)。

默認(rèn)配置下,spring只有在拋出的異常為運行時unchecked異常時才回滾該事務(wù),也就是拋出的異常為RuntimeException的子類(Errors也會導(dǎo)致事務(wù)回滾),而拋出checked異常則不會導(dǎo)致事務(wù)回滾。

可以明確的配置在拋出那些異常時回滾事務(wù),包括checked異常。也可以明確定義那些異常拋出時不回滾事務(wù)。

還可以編程性的通過setRollbackOnly()方法來指示一個事務(wù)必須回滾,在調(diào)用完setRollbackOnly()后你所能執(zhí)行的唯一操作就是回滾。

@Transactional注解

@Transactional屬性

屬性 類型 描述
value String 可選的限定描述符,指定使用的事務(wù)管理器
propagation enum: Propagation 可選的事務(wù)傳播行為設(shè)置
isolation enum: Isolation 可選的事務(wù)隔離級別設(shè)置
readOnly boolean 讀寫或只讀事務(wù),默認(rèn)讀寫
timeout int (in seconds granularity) 事務(wù)超時時間設(shè)置
rollbackFor Class對象數(shù)組,必須繼承自Throwable 導(dǎo)致事務(wù)回滾的異常類數(shù)組
rollbackForClassName 類名數(shù)組,必須繼承自Throwable 導(dǎo)致事務(wù)回滾的異常類名字?jǐn)?shù)組
noRollbackFor Class對象數(shù)組,必須繼承自Throwable 不會導(dǎo)致事務(wù)回滾的異常類數(shù)組
noRollbackForClassName 類名數(shù)組,必須繼承自Throwable 不會導(dǎo)致事務(wù)回滾的異常類名字?jǐn)?shù)組

用法

@Transactional 可以作用于接口、接口方法、類以及類方法上。當(dāng)作用于類上時,該類的所有 public 方法將都具有該類型的事務(wù)屬性,同時,我們也可以在方法級別使用該標(biāo)注來覆蓋類級別的定義。

雖然 @Transactional 注解可以作用于接口、接口方法、類以及類方法上,但是 Spring 建議不要在接口或者接口方法上使用該注解,因為這只有在使用基于接口的代理時它才會生效。另外, @Transactional 注解應(yīng)該只被應(yīng)用到 public 方法上,這是由 Spring AOP 的本質(zhì)決定的。如果你在 protected、private 或者默認(rèn)可見性的方法上使用 @Transactional 注解,這將被忽略,也不會拋出任何異常。

默認(rèn)情況下,只有來自外部的方法調(diào)用才會被AOP代理捕獲,也就是,類內(nèi)部方法調(diào)用本類內(nèi)部的其他方法并不會引起事務(wù)行為,即使被調(diào)用方法使用@Transactional注解進(jìn)行修飾。

@Transactional(readOnly = true)
public class DefaultFooService implements FooService {
	public Foo getFoo(String fooName) {
		// do something
	}
	// these settings have precedence for this method
	//方法上注解屬性會覆蓋類注解上的相同屬性
	@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
	 public void updateFoo(Foo foo) {
		// do something
	}
}

總結(jié)

以上就是本文關(guān)于spring的@Transactional注解用法解讀的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

相關(guān)文章

  • Java中==和equals()的區(qū)別總結(jié)

    Java中==和equals()的區(qū)別總結(jié)

    ==和equals是我們面試中經(jīng)常會碰到的問題,那么它們之間有什么聯(lián)系和區(qū)別呢?這篇文章主要給大家介紹了關(guān)于Java中==和equals()區(qū)別的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • 詳解eclipse項目中的.classpath文件原理

    詳解eclipse項目中的.classpath文件原理

    這篇文章介紹了eclipse項目中的.classpath文件的原理,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • java前后端使用ajax數(shù)據(jù)交互問題(簡單demo)

    java前后端使用ajax數(shù)據(jù)交互問題(簡單demo)

    這篇文章主要介紹了java前后端使用ajax數(shù)據(jù)交互問題(簡單demo),具有很好的參考價值,希望對大家有所幫助。
    2023-06-06
  • 利用Spring框架為自己的校園卡充值(推薦)

    利用Spring框架為自己的校園卡充值(推薦)

    這篇文章主要介紹了利用Spring框架為自己的校園卡充值,本次實驗主要運用了Spring的控制反轉(zhuǎn)(IOC)和依賴注入(DI)等知識,通過利用Spring框架編寫Java程序,實現(xiàn)學(xué)生卡的單次充值,如需對學(xué)生卡進(jìn)行多次充值,可將部分代碼修改即可實現(xiàn),需要的朋友可以參考下
    2022-10-10
  • Java if(boolean)和if(boolean=true)區(qū)別解析

    Java if(boolean)和if(boolean=true)區(qū)別解析

    這篇文章主要介紹了Java if(boolean)和if(boolean=true)區(qū)別解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • Java  匿名內(nèi)部類詳解及實例代碼

    Java 匿名內(nèi)部類詳解及實例代碼

    這篇文章主要介紹了Java 匿名內(nèi)部類詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • window下安裝和配置maven環(huán)境

    window下安裝和配置maven環(huán)境

    這篇文章主要為大家詳細(xì)介紹了window下安裝和配置maven環(huán)境的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • 詳解JAVA中implement和extends的區(qū)別

    詳解JAVA中implement和extends的區(qū)別

    這篇文章主要介紹了詳解JAVA中implement和extends的區(qū)別的相關(guān)資料,extends是繼承接口,implement是一個類實現(xiàn)一個接口的關(guān)鍵字,需要的朋友可以參考下
    2017-08-08
  • java多線程批量拆分List導(dǎo)入數(shù)據(jù)庫的實現(xiàn)過程

    java多線程批量拆分List導(dǎo)入數(shù)據(jù)庫的實現(xiàn)過程

    這篇文章主要給大家介紹了關(guān)于java多線程批量拆分List導(dǎo)入數(shù)據(jù)庫的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2021-10-10
  • Spring整合Junit的使用詳解

    Spring整合Junit的使用詳解

    這篇文章主要介紹了Spring整合Junit的使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02

最新評論