spring,mybatis事務管理配置與@Transactional注解使用

spring,mybatis事務管理配置與@Transactional注解使用

概述

事務管理對于企業(yè)應用來說是至關重要的沼溜,即使出現(xiàn)異常情況,它也可以保證數(shù)據(jù)的一致性。Spring Framework對事務管理提供了一致的抽象,其特點如下:
為不同的事務API提供一致的編程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)
支持聲明式事務管理批狱,特別是基于注解的聲明式事務管理,簡單易用
提供比其他事務API如JTA更簡單的編程式事務管理API
與spring數(shù)據(jù)訪問抽象的完美集成

事務管理方式

spring支持編程式事務管理和聲明式事務管理兩種方式展东。

  • 編程式事務管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager赔硫。對于編程式事務管理,spring推薦使用TransactionTemplate盐肃。
  • 聲明式事務管理建立在AOP之上的爪膊。其本質(zhì)是對方法前后進行攔截,然后在目標方法開始之前創(chuàng)建或者加入一個事務砸王,在執(zhí)行完目標方法之后根據(jù)執(zhí)行情況提交或者回滾事務推盛。聲明式事務最大的優(yōu)點就是不需要通過編程的方式管理事務,這樣就不需要在業(yè)務邏輯代碼中摻雜事務管理的代碼谦铃,只需在配置文件中做相關的事務規(guī)則聲明(或通過基于@Transactional注解的方式)耘成,便可以將事務規(guī)則應用到業(yè)務邏輯中。
    顯然聲明式事務管理要優(yōu)于編程式事務管理驹闰,這正是spring倡導的非侵入式的開發(fā)方式瘪菌。聲明式事務管理使業(yè)務代碼不受污染,一個普通的POJO對象嘹朗,只要加上注解就可以獲得完全的事務支持师妙。和編程式事務相比,聲明式事務唯一不足地方是骡显,后者的最細粒度只能作用到方法級別疆栏,無法做到像編程式事務那樣可以作用到代碼塊級別。但是即便有這樣的需求惫谤,也存在很多變通的方法壁顶,比如,可以將需要進行事務管理的代碼塊獨立為方法等等溜歪。
    聲明式事務管理也有兩種常用的方式若专,一種是基于tx和aop名字空間的xml配置文件,另一種就是基于@Transactional注解蝴猪。顯然基于注解的方式更簡單易用调衰,更清爽。
    自動提交(AutoCommit)與連接關閉時的是否自動提交
    自動提交
    默認情況下自阱,數(shù)據(jù)庫處于自動提交模式嚎莉。每一條語句處于一個單獨的事務中,在這條語句執(zhí)行完畢時沛豌,如果執(zhí)行成功則隱式的提交事務趋箩,如果執(zhí)行失敗則隱式的回滾事務。
    對于正常的事務管理加派,是一組相關的操作處于一個事務之中叫确,因此必須關閉數(shù)據(jù)庫的自動提交模式。不過芍锦,這個我們不用擔心竹勉,spring會將底層連接的自動提交特性設置為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ù)連接池提供了關閉事務自動提交的設置娄琉,最好在設置連接池時就將其關閉次乓。比如DBCP連接池, 默認的配置是自動提交.

package org.apache.commons.dbcp;
public class BasicDataSource implements DataSource {    protected volatile boolean defaultAutoCommit = true;
...

所以在配置文件中要修改配置,如下

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
   ...
   <property name="defaultAutoCommit" value="false"/>
</bean>

但C3P0沒有提供這一特性,只能依靠spring來設置车胡。因為JDBC規(guī)范規(guī)定檬输,當連接對象建立時應該處于自動提交模式,這是跨DBMS的缺省值匈棘,如果需要,必須顯式的關閉自動提交丧慈。C3P0遵守這一規(guī)范,讓客戶代碼來顯式的設置需要的提交模式主卫。
連接關閉時的是否自動提交
當一個連接關閉時胰耗,如果有未提交的事務應該如何處理?JDBC規(guī)范沒有提及凛篙,C3P0默認的策略是回滾任何未提交的事務嘱朽。這是一個正確的策略,但JDBC驅(qū)動提供商之間對此問題并沒有達成一致瘩将。C3P0的autoCommitOnClose屬性默認是false,沒有十分必要不要動它吟税“及遥或者可以顯式的設置此屬性為false,這樣會更明確肠仪。
基于注解的聲明式事務管理配置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事務管理中肖抱,無需額外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的數(shù)據(jù)源與DataSourceTransactionManager引用的數(shù)據(jù)源一致即可异旧,否則事務管理會不起作用意述。
另外需要下載依賴包aopalliance.jar放置到WEB-INF/lib目錄下,
否則spring初始化時會報異常java.lang.NoClassDefFoundError:
org/aopalliance/intercept/MethodInterceptor
spring事務特性
spring所有的事務管理策略類都繼承自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接口定義以下特性:

事務隔離級別

隔離級別是指若干個并發(fā)的事務之間的隔離程度。

  • TransactionDefinition 接口中定義了五個表示隔離級別的常量:
    TransactionDefinition.ISOLATION_DEFAULT:這是默認值吮蛹,表示使用底層數(shù)據(jù)庫的默認隔離級別荤崇。對大部分數(shù)據(jù)庫而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED潮针。

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

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

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

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

MySQL/InnoDB 提供SQL標準所描述的所有四個事務隔離級別

事務傳播行為

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

  • TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務夕春;如果當前沒有事務未荒,則創(chuàng)建一個新的事務。這是默認值及志。
  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:創(chuàng)建一個新的事務片排,如果當前存在事務寨腔,則把當前事務掛起。
  • TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務率寡,則加入該事務脆侮;如果當前沒有事務,則以非事務的方式繼續(xù)運行勇劣。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務潭枣,則把當前事務掛起比默。
  • TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務盆犁,則拋出異常命咐。
  • TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務谐岁;如果當前沒有事務醋奠,則拋出異常。
  • TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務伊佃,則創(chuàng)建一個事務作為當前事務的嵌套事務來運行窜司;如果當前沒有事務,則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED航揉。

事務超時

所謂事務超時塞祈,就是指一個事務所允許執(zhí)行的最長時間,如果超過該時間限制但事務還沒有完成帅涂,則自動回滾事務议薪。在 TransactionDefinition 中以 int 的值來表示超時時間,其單位是秒媳友。
默認設置為底層事務系統(tǒng)的超時值斯议,如果底層數(shù)據(jù)庫事務系統(tǒng)沒有設置超時值,那么就是none醇锚,沒有超時限制哼御。
事務只讀屬性
只讀事務用于客戶代碼只讀但不修改數(shù)據(jù)的情形,只讀事務用于特定情景下的優(yōu)化焊唬,比如使用Hibernate的時候艇搀。默認為讀寫事務。
spring事務回滾規(guī)則
指示spring事務管理器回滾一個事務的推薦方法是在當前事務的上下文內(nèi)拋出異常求晶。spring事務管理器會捕捉任何未處理的異常焰雕,然后依據(jù)規(guī)則決定是否回滾拋出異常的事務。
默認配置下芳杏,spring只有在拋出的異常為運行時unchecked異常時才回滾該事務矩屁,也就是拋出的異常為RuntimeException的子類(Errors也會導致事務回滾)辟宗,而拋出checked異常則不會導致事務回滾×唢酰可以明確的配置在拋出那些異常時回滾事務泊脐,包括checked異常。也可以明確定義那些異常拋出時不回滾事務烁峭。
還可以編程性的通過setRollbackOnly()方法來指示一個事務必須回滾容客,在調(diào)用完setRollbackOnly()后你所能執(zhí)行的唯一操作就是回滾。
@Transactional注解
@Transactional屬性

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

用法
@Transactional 可以作用于接口绽快、接口方法芥丧、類以及類方法上。當作用于類上時坊罢,該類的所有 public 方法將都具有該類型的事務屬性续担,同時,我們也可以在方法級別使用該標注來覆蓋類級別的定義活孩。
雖然 @Transactional 注解可以作用于接口赤拒、接口方法、類以及類方法上诱鞠,但是 Spring 建議不要在接口或者接口方法上使用該注解挎挖,因為這只有在使用基于接口的代理時它才會生效。另外航夺, @Transactional 注解應該只被應用到 public 方法上蕉朵,這是由 Spring AOP 的本質(zhì)決定的。如果你在 protected阳掐、private 或者默認可見性的方法上使用 @Transactional 注解始衅,這將被忽略,也不會拋出任何異常缭保。
默認情況下汛闸,只有來自外部的方法調(diào)用才會被AOP代理捕獲,也就是艺骂,類內(nèi)部方法調(diào)用本類內(nèi)部的其他方法并不會引起事務行為诸老,即使被調(diào)用方法使用@Transactional注解進行修飾。
示例代碼:

@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
  }
}

參考
http://docs.spring.io/spring/docs/3.2.4.RELEASE/spring-framework-reference/html/transaction.html
http://openwares.net/java/spring_mybatis_transaction.html
http://www.cnblogs.com/zhoujinyi/p/3437475.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钳恕,一起剝皮案震驚了整個濱河市别伏,隨后出現(xiàn)的幾起案子蹄衷,更是在濱河造成了極大的恐慌,老刑警劉巖厘肮,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愧口,死亡現(xiàn)場離奇詭異,居然都是意外死亡类茂,警方通過查閱死者的電腦和手機耍属,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來巩检,“玉大人厚骗,你說我怎么就攤上這事〔杲恚” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵丑搔,是天一觀的道長厦瓢。 經(jīng)常有香客問我,道長啤月,這世上最難降的妖魔是什么煮仇? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮谎仲,結(jié)果婚禮上浙垫,老公的妹妹穿的比我還像新娘。我一直安慰自己郑诺,他們只是感情好夹姥,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著辙诞,像睡著了一般辙售。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上飞涂,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天旦部,我揣著相機與錄音,去河邊找鬼较店。 笑死士八,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的梁呈。 我是一名探鬼主播婚度,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼官卡!你這毒婦竟也來了陕见?” 一聲冷哼從身側(cè)響起秘血,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎评甜,沒想到半個月后灰粮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡忍坷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年粘舟,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佩研。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡柑肴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旬薯,到底是詐尸還是另有隱情晰骑,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布绊序,位于F島的核電站硕舆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏骤公。R本人自食惡果不足惜抚官,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阶捆。 院中可真熱鬧凌节,春花似錦、人聲如沸洒试。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽垒棋。三九已至娱挨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捕犬,已是汗流浹背跷坝。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碉碉,地道東北人柴钻。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像垢粮,于是被迫代替她去往敵國和親贴届。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 很多人喜歡這篇文章,特此同步過來 由淺入深談論spring事務 前言 這篇其實也要歸納到《常識》系列中毫蚓,但這重點又...
    碼農(nóng)戲碼閱讀 4,706評論 2 59
  • spring支持編程式事務管理和聲明式事務管理兩種方式占键。 編程式事務管理使用TransactionTemplate...
    熊熊要更努力閱讀 245評論 0 0
  • 這部分的參考文檔涉及數(shù)據(jù)訪問和數(shù)據(jù)訪問層和業(yè)務或服務層之間的交互。 Spring的綜合事務管理支持覆蓋很多細節(jié)元潘,然...
    竹天亮閱讀 1,029評論 0 0
  • 事務有四個特性:ACID 原子性(Atomicity):事務是一個原子操作畔乙,由一系列動作組成。事務的原子性確保動作...
    jiangmo閱讀 1,224評論 0 7
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評論 6 342