http://blog.csdn.net/bao19901210/article/details/41724355html
http://www.cnblogs.com/leiOOlei/p/3725911.htmljava
事物管理對於企業應用來講是相當重要的,好使出現異常狀況,它也能夠保證數據的一致性。mysql
spring支持編程式事務管理和聲明式事務管理兩種方式。spring
編程式事務管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對於編程式事務管理,spring推薦使用TransactionTemplate。sql
聲明式事務管理創建在AOP之上的。其本質是對方法先後進行攔截,而後在目標方法開始以前建立或者加入一個事務,在執行完目標方法以後根據執行狀況提交或者回滾事務。聲明式事務最大的優勢就是不須要經過編程的方式管理事務,這樣就不須要在業務邏輯代碼中摻瑣事務管理的代碼,只需在配置文件中作相關的事務規則聲明(或經過基於@Transactional註解的方式),即可以將事務規則應用到業務邏輯中。數據庫
顯然聲明式事務管理要優於編程式事務管理,這正是spring倡導的非侵入式的開發方式。聲明式事務管理使業務代碼不受污染,一個普通的POJO對象,只要加上註解就能夠得到徹底的事務支持。和編程式事務相比,聲明式事務惟一不足地方是,後者的最細粒度只能做用到方法級別,沒法作到像編程式事務那樣能夠做用到代碼塊級別。可是即使有這樣的需求,也存在不少變通的方法,好比,能夠將須要進行事務管理的代碼塊獨立爲方法等等。express
聲明式事務管理也有兩種經常使用的方式,一種是基於tx和aop名字空間的xml配置文件,另外一種就是基於@Transactional註解。顯然基於註解的方式更簡單易用,更清爽。編程
spring事務特性數組
spring全部的事務管理策略類都繼承自org.springframework.transaction.PlatformTransactionManager接口性能優化
其中TransactionDefinition接口定義如下特性:
事務隔離級別
隔離級別是指若干個併發的事務之間的隔離程度。TransactionDefinition 接口中定義了五個表示隔離級別的常量:
- TransactionDefinition.ISOLATION_DEFAULT:這是默認值,表示使用底層數據庫的默認隔離級別。對大部分數據庫而言,一般這值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級別表示一個事務能夠讀取另外一個事務修改但尚未提交的數據。該級別不能防止髒讀,不可重複讀和幻讀,所以不多使用該隔離級別。好比PostgreSQL實際上並無此級別。
- TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級別表示一個事務只能讀取另外一個事務已經提交的數據。該級別能夠防止髒讀,這也是大多數狀況下的推薦值。
- TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級別表示一個事務在整個過程當中能夠屢次重複執行某個查詢,而且每次返回的記錄都相同。該級別能夠防止髒讀和不可重複讀。
- TransactionDefinition.ISOLATION_SERIALIZABLE:全部的事務依次逐個執行,這樣事務之間就徹底不可能產生干擾,也就是說,該級別能夠防止髒讀、不可重複讀以及幻讀。可是這將嚴重影響程序的性能。一般狀況下也不會用到該級別。
事務傳播行爲
所謂事務的傳播行爲是指,若是在開始當前事務以前,一個事務上下文已經存在,此時有若干選項能夠指定一個事務性方法的執行行爲。在TransactionDefinition定義中包括了以下幾個表示傳播行爲的常量:
- 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。
事務超時
所謂事務超時,就是指一個事務所容許執行的最長時間,若是超過該時間限制但事務尚未完成,則自動回滾事務。在 TransactionDefinition 中以 int 的值來表示超時時間,其單位是秒。
默認設置爲底層事務系統的超時值,若是底層數據庫事務系統沒有設置超時值,那麼就是none,沒有超時限制。
事務只讀屬性
只讀事務用於客戶代碼只讀但不修改數據的情形,只讀事務用於特定情景下的優化,好比使用Hibernate的時候。
默認爲讀寫事務。
「只讀事務」並非一個強制選項,它只是一個「暗示」,提示數據庫驅動程序和數據庫系統,這個事務並不包含更改數據的操做,那麼JDBC驅動程序和數據庫就有可能根據這種狀況對該事務進行一些特定的優化,比方說不安排相應的數據庫鎖,以減輕事務對數據庫的壓力,畢竟事務也是要消耗數據庫的資源的。
可是你非要在「只讀事務」裏面修改數據,也並不是不能夠,只不過對於數據一致性的保護不像「讀寫事務」那樣保險而已。
所以,「只讀事務」僅僅是一個性能優化的推薦配置而已,並不是強制你要這樣作不可
spring事務回滾規則
指示spring事務管理器回滾一個事務的推薦方法是在當前事務的上下文內拋出異常。spring事務管理器會捕捉任何未處理的異常,而後依據規則決定是否回滾拋出異常的事務。
默認配置下,spring只有在拋出的異常爲運行時unchecked異常時纔回滾該事務,也就是拋出的異常爲RuntimeException的子類(Errors也會致使事務回滾),而拋出checked異常則不會致使事務回滾。能夠明確的配置在拋出那些異常時回滾事務,包括checked異常。也能夠明肯定義那些異常拋出時不回滾事務。還能夠編程性的經過setRollbackOnly()方法來指示一個事務必須回滾,在調用完setRollbackOnly()後你所能執行的惟一操做就是回滾。
- myBatis爲例 基於註解的聲明式事務管理配置@Transactional
spring.xml
- <span style="background-color: rgb(255, 255, 255);"><span style="background-color: rgb(255, 204, 153);">
- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <property name="configLocation">
- <value>classpath:mybatis-config.xml</value>
- </property>
- </bean>
-
-
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage">
- <value>
- com.baobao.persistence.test
- </value>
- </property>
- <property name="sqlSessionFactory" ref="sqlSessionFactory" />
- </bean>
-
-
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource" />
- </bean>
-
-
- <tx:annotation-driven transaction-manager="transactionManager"/></span></span>
添加tx名字空間
- <span style="background-color: rgb(255, 255, 255);"><span style="background-color: rgb(255, 204, 153);">xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
-
- xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"</span></span>
MyBatis自動參與到spring事務管理中,無需額外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的數據源與DataSourceTransactionManager引用的數據源一致便可,不然事務管理會不起做用。
@Transactional註解
@Transactional屬性
屬性 |
類型 |
描述 |
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 |
不會致使事務回滾的異常類名字數組 |
用法
@Transactional 能夠做用於接口、接口方法、類以及類方法上。看成用於類上時,該類的全部 public 方法將都具備該類型的事務屬性,同時,咱們也能夠在方法級別使用該標註來覆蓋類級別的定義。
雖然 @Transactional 註解能夠做用於接口、接口方法、類以及類方法上,可是 Spring 建議不要在接口或者接口方法上使用該註解,由於這隻有在使用基於接口的代理時它纔會生效。另外, @Transactional 註解應該只被應用到 public 方法上,這是由 Spring AOP 的本質決定的。若是你在 protected、private 或者默承認見性的方法上使用 @Transactional 註解,這將被忽略,也不會拋出任何異常。
默認狀況下,只有來自外部的方法調用纔會被AOP代理捕獲,也就是,類內部方法調用本類內部的其餘方法並不會引發事務行爲,即便被調用方法使用@Transactional註解進行修飾。
- @Autowired
- private MyBatisDao dao;
-
- @Transactional
- @Override
- public void insert(Test test) {
- dao.insert(test);
- throw new RuntimeException("test");
- }
noRollbackFor
- @Transactional(noRollbackFor=RuntimeException.class)
- @Override
- public void insert(Test test) {
- dao.insert(test);
-
- throw new RuntimeException("test");
- }
類,看成用於類上時,該類的全部 public 方法將都具備該類型的事務屬性
- @Transactional
- public class MyBatisServiceImpl implements MyBatisService {
-
- @Autowired
- private MyBatisDao dao;
-
-
- @Override
- public void insert(Test test) {
- dao.insert(test);
-
- throw new RuntimeException("test");
- }
propagation=Propagation.NOT_SUPPORTED
- @Transactional(propagation=Propagation.NOT_SUPPORTED)
- @Override
- public void insert(Test test) {
-
- dao.insert(test);
- }
- myBatis爲例 基於註解的聲明式事務管理配置,xml配置
主要爲aop切面配置,只看xml就能夠了
- <tx:advice id="advice" transaction-manager="transactionManager">
- <tx:attributes>
- <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>
- <tx:method name="insert" propagation="REQUIRED" read-only="false"/>
- </tx:attributes>
- </tx:advice>
-
- <aop:config>
- <aop:pointcut id="testService" expression="execution (* com.baobao.service.MyBatisService.*(..))"/>
- <aop:advisor advice-ref="advice" pointcut-ref="testService"/>
- </aop:config>