Spring的編程式事務(wù)和聲明式事務(wù)

事務(wù)管理對(duì)于企業(yè)應(yīng)用來(lái)說(shuō)是至關(guān)重要的取刃,當(dāng)出現(xiàn)異常情況時(shí)吧彪,它也可以保證數(shù)據(jù)的一致性待侵。

Spring事務(wù)管理的兩種方式

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

  • 編程式事務(wù)使用TransactionTemplate或者直接使用底層的PlatformTransactionManager姨裸。對(duì)于編程式事務(wù)管理秧倾,spring推薦使用TransactionTemplate香拉。
  • 聲明式事務(wù)是建立在AOP之上的。其本質(zhì)是對(duì)方法前后進(jìn)行攔截中狂,然后在目標(biāo)方法開(kāi)始之前創(chuàng)建或者加入一個(gè)事務(wù)凫碌,在執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行情況提交或者回滾事務(wù)。聲明式事務(wù)最大的優(yōu)點(diǎn)就是不需要通過(guò)編程的方式管理事務(wù)胃榕,這樣就不需要在業(yè)務(wù)邏輯代碼中摻雜事務(wù)管理的代碼盛险,只需在配置文件中做相關(guān)的事務(wù)規(guī)則聲明(或通過(guò)基于@Transactional注解的方式),便可以將事務(wù)規(guī)則應(yīng)用到業(yè)務(wù)邏輯中勋又。

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

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

spring事務(wù)特性

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

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

事務(wù)隔離級(jí)別

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

  • TransactionDefinition.ISOLATION_DEFAULT:這是默認(rèn)值县习,表示使用底層數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別涮母。對(duì)大部分?jǐn)?shù)據(jù)庫(kù)而言,通常這值就是TransactionDefinition.ISOLATION_READ_COMMITTED躁愿。
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級(jí)別表示一個(gè)事務(wù)可以讀取另一個(gè)事務(wù)修改但還沒(méi)有提交的數(shù)據(jù)。該級(jí)別不能防止臟讀沪蓬,不可重復(fù)讀和幻讀彤钟,因此很少使用該隔離級(jí)別。比如PostgreSQL實(shí)際上并沒(méi)有此級(jí)別跷叉。
  • TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級(jí)別表示一個(gè)事務(wù)只能讀取另一個(gè)事務(wù)已經(jīng)提交的數(shù)據(jù)逸雹。該級(jí)別可以防止臟讀营搅,這也是大多數(shù)情況下的推薦值。
  • TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級(jí)別表示一個(gè)事務(wù)在整個(gè)過(guò)程中可以多次重復(fù)執(zhí)行某個(gè)查詢梆砸,并且每次返回的記錄都相同。該級(jí)別可以防止臟讀和不可重復(fù)讀帖世。
  • TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務(wù)依次逐個(gè)執(zhí)行,這樣事務(wù)之間就完全不可能產(chǎn)生干擾日矫,也就是說(shuō),該級(jí)別可以防止臟讀盈魁、不可重復(fù)讀以及幻讀。但是這將嚴(yán)重影響程序的性能杨耙。通常情況下也不會(huì)用到該級(jí)別飘痛。

事務(wù)傳播行為

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

  • TransactionDefinition.PROPAGATION_REQUIRED:如果當(dāng)前存在事務(wù)萌庆,則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù)践险,則創(chuàng)建一個(gè)新的事務(wù)。這是默認(rèn)值巍虫。
  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù)俯抖,則把當(dāng)前事務(wù)掛起瓦胎。
  • TransactionDefinition.PROPAGATION_SUPPORTS:如果當(dāng)前存在事務(wù)尤揣,則加入該事務(wù)柬祠;如果當(dāng)前沒(méi)有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行漫蛔。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù)芝硬,則把當(dāng)前事務(wù)掛起轧房。
  • TransactionDefinition.PROPAGATION_NEVER:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù)奶镶,則拋出異常。
  • TransactionDefinition.PROPAGATION_MANDATORY:如果當(dāng)前存在事務(wù)纤壁,則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù)酌媒,則拋出異常迄靠。
  • TransactionDefinition.PROPAGATION_NESTED:如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來(lái)運(yùn)行掌挚;如果當(dāng)前沒(méi)有事務(wù),則該取值等價(jià)于TransactionDefinition.PROPAGATION_REQUIRED陡厘。

事務(wù)超時(shí)

所謂事務(wù)超時(shí)特占,就是指一個(gè)事務(wù)所允許執(zhí)行的最長(zhǎng)時(shí)間,如果超過(guò)該時(shí)間限制但事務(wù)還沒(méi)有完成罢低,則自動(dòng)回滾事務(wù)。在 TransactionDefinition 中以 int 的值來(lái)表示超時(shí)時(shí)間胖笛,其單位是秒。

默認(rèn)設(shè)置為底層事務(wù)系統(tǒng)的超時(shí)值功舀,如果底層數(shù)據(jù)庫(kù)事務(wù)系統(tǒng)沒(méi)有設(shè)置超時(shí)值身弊,那么就是none,沒(méi)有超時(shí)限制帖汞。

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

默認(rèn)配置下,spring只有在拋出的異常為運(yùn)行時(shí)unchecked異常時(shí)才回滾該事務(wù)翩蘸,也就是拋出的異常為RuntimeException的子類(Errors也會(huì)導(dǎo)致事務(wù)回滾)淮逊,而拋出checked異常則不會(huì)導(dǎo)致事務(wù)回滾±扇危可以明確的配置在拋出哪些異常時(shí)回滾事務(wù)备籽,包括checked異常。也可以明確定義那些異常拋出時(shí)不回滾事務(wù)霉猛。還可以編程性的通過(guò)setRollbackOnly()方法來(lái)指示一個(gè)事務(wù)必須回滾,在調(diào)用完setRollbackOnly()后你所能執(zhí)行的唯一操作就是回滾韩脏。

以MyBatis為例,基于注解的聲明式事務(wù)配置

1赡矢、添加tx名字空間

xmlns:tx="http://www.springframework.org/schema/tx"

2阅仔、開(kāi)啟事務(wù)的注解支持

<!-- 開(kāi)啟事務(wù)控制的注解支持 -->  
<tx:annotation-driven transaction-manager="transactionManager"/>

3、MyBatis自動(dòng)參與到spring事務(wù)管理中八酒,無(wú)需額外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的數(shù)據(jù)源與DataSourceTransactionManager引用的數(shù)據(jù)源一致即可界轩。

<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 id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    <property name="dataSource" ref="dataSource" />  
</bean>  

4浊猾、使用@Transactional注解

@Transactional 可以作用于接口、接口方法葫慎、類以及類方法上衔彻。當(dāng)作用于類上時(shí)艰额,該類的所有 public 方法將都具有該類型的事務(wù)屬性椒涯,同時(shí),我們也可以在方法級(jí)別使用該注解來(lái)覆蓋類級(jí)別的定義逐工。

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

以MyBatis為例,基于.xml文件的聲明式事務(wù)配置

<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.nnngu.service.MyBatisService.*(..))"/>  
    <aop:advisor advice-ref="advice" pointcut-ref="testService"/>  
</aop:config>  

本文永久更新地址:https://github.com/nnngu/LearningNotes/blob/master/_posts/2018-03-22-Spring%E7%9A%84%E7%BC%96%E7%A8%8B%E5%BC%8F%E4%BA%8B%E5%8A%A1%E5%92%8C%E5%A3%B0%E6%98%8E%E5%BC%8F%E4%BA%8B%E5%8A%A1.md

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市篓跛,隨后出現(xiàn)的幾起案子坦刀,更是在濱河造成了極大的恐慌,老刑警劉巖鲤遥,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盖奈,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡究孕,警方通過(guò)查閱死者的電腦和手機(jī)爹凹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)微酬,“玉大人颤陶,你說(shuō)我怎么就攤上這事∽易撸” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵比吭,是天一觀的道長(zhǎng)梗逮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)绣溜,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任岁诉,我火速辦了婚禮跋选,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘前标。我一直安慰自己,他們只是感情好只搁,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布俭尖。 她就那樣靜靜地躺著,像睡著了一般焰望。 火紅的嫁衣襯著肌膚如雪已亥。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天秫舌,我揣著相機(jī)與錄音绣檬,去河邊找鬼娇未。 笑死,一個(gè)胖子當(dāng)著我的面吹牛零抬,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蝶棋,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼忽妒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼玩裙!你這毒婦竟也來(lái)了兼贸?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吃溅,失蹤者是張志新(化名)和其女友劉穎溶诞,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體决侈,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡螺垢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赖歌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片枉圃。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖俏站,靈堂內(nèi)的尸體忽然破棺而出讯蒲,到底是詐尸還是另有隱情,我是刑警寧澤肄扎,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站赁酝,受9級(jí)特大地震影響犯祠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜酌呆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一衡载、第九天 我趴在偏房一處隱蔽的房頂上張望痰娱。 院中可真熱鬧,春花似錦娜饵、人聲如沸遍坟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)瞬雹。三九已至酗捌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阀圾,已是汗流浹背涡真。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留东亦,地道東北人典阵。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓蹋半,卻偏偏與公主長(zhǎng)得像染突,于是被迫代替她去往敵國(guó)和親份企。 傳聞我的和親對(duì)象是個(gè)殘疾皇子司志,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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