日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

spring事务配置,声明式事务管理和基于@Transactional注解的使用

發(fā)布時(shí)間:2025/3/20 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring事务配置,声明式事务管理和基于@Transactional注解的使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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

spring提供了幾個(gè)關(guān)于事務(wù)處理的類(lèi):
TransactionDefinition //事務(wù)屬性定義
TranscationStatus //代表了當(dāng)前的事務(wù),可以提交,回滾。
PlatformTransactionManager這個(gè)是spring提供的用于管理事務(wù)的基礎(chǔ)接口,其下有一個(gè)實(shí)現(xiàn)的抽象類(lèi) AbstractPlatformTransactionManager,我們使用的事務(wù)管理類(lèi)例如 DataSourceTransactionManager等都是這個(gè)類(lèi)的子類(lèi)。


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ú)立為方法等等。

編程式的,比較靈活,但是代碼量大,存在重復(fù)的代碼比較多;聲明式的比編程式的更靈活。

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

spring事務(wù)特性

spring所有的事務(wù)管理策略類(lèi)都繼承自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è)查詢(xún),并且每次返回的記錄都相同。該級(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í)限制。

事務(wù)只讀屬性

? ? ??只讀事務(wù)用于客戶(hù)代碼只讀但不修改數(shù)據(jù)的情形,只讀事務(wù)用于特定情景下的優(yōu)化,比如使用Hibernate的時(shí)候。 默認(rèn)為讀寫(xiě)事務(wù)。


? ? ? ??“只讀事務(wù)”并不是一個(gè)強(qiáng)制選項(xiàng),它只是一個(gè)“暗示”,提示數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序和數(shù)據(jù)庫(kù)系統(tǒng),這個(gè)事務(wù)并不包含更改數(shù)據(jù)的操作,那么JDBC驅(qū)動(dòng)程序和數(shù)據(jù)庫(kù)就有可能根據(jù)這種情況對(duì)該事務(wù)進(jìn)行一些特定的優(yōu)化,比方說(shuō)不安排相應(yīng)的數(shù)據(jù)庫(kù)鎖,以減輕事務(wù)對(duì)數(shù)據(jù)庫(kù)的壓力,畢竟事務(wù)也是要消耗數(shù)據(jù)庫(kù)的資源的。?

但是你非要在“只讀事務(wù)”里面修改數(shù)據(jù),也并非不可以,只不過(guò)對(duì)于數(shù)據(jù)一致性的保護(hù)不像“讀寫(xiě)事務(wù)”那樣保險(xiǎn)而已。?

因此,“只讀事務(wù)”僅僅是一個(gè)性能優(yōu)化的推薦配置而已,并非強(qiáng)制你要這樣做不可


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

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

? ? ? ? 默認(rèn)配置下,spring只有在拋出的異常為運(yùn)行時(shí)unchecked異常時(shí)才回滾該事務(wù),也就是拋出的異常為RuntimeException的子類(lèi)(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ù)管理配置@Transactional

spring.xml

[html]?view plain?copy
  • <span?style="background-color:?rgb(255,?255,?255);"><span?style="background-color:?rgb(255,?204,?153);"><!--?mybatis?config?-->??
  • ????<bean?id="sqlSessionFactory"?class="org.mybatis.spring.SqlSessionFactoryBean">??
  • ????????<property?name="dataSource"?ref="dataSource"?/>??
  • ????????<property?name="configLocation">??
  • ????????????<value>classpath:mybatis-config.xml</value>??
  • ????????</property>??
  • ????</bean>??
  • ??????
  • ????<!--?mybatis?mappers,?scanned?automatically?-->??
  • ????<bean?class="org.mybatis.spring.mapper.MapperScannerConfigurer">??
  • ????????<property?name="basePackage">??
  • ????????????<value>??
  • ????????????????com.baobao.persistence.test??
  • ????????????</value>??
  • ????????</property>??
  • ????????<property?name="sqlSessionFactory"?ref="sqlSessionFactory"?/>??
  • ????</bean>??
  • ??????
  • ????<!--?配置spring的PlatformTransactionManager,名字為默認(rèn)值?-->??
  • ????<bean?id="transactionManager"?class="org.springframework.jdbc.datasource.DataSourceTransactionManager">??
  • ????????<property?name="dataSource"?ref="dataSource"?/>??
  • ????</bean>??
  • ??????
  • ????<!--?開(kāi)啟事務(wù)控制的注解支持?-->??
  • ????<tx:annotation-driven?transaction-manager="transactionManager"/></span></span>??
  • 添加tx名字空間
    [html]?view plain?copy
  • <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自動(dòng)參與到spring事務(wù)管理中,無(wú)需額外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的數(shù)據(jù)源與DataSourceTransactionManager引用的數(shù)據(jù)源一致即可,否則事務(wù)管理會(huì)不起作用。

    @Transactional注解

    @Transactional屬性?

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

    用法

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

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

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

    [java]?view plain?copy
  • @Autowired??
  • private?MyBatisDao?dao;??
  • ??
  • @Transactional??
  • @Override??
  • public?void?insert(Test?test)?{??
  • ????dao.insert(test);??
  • ????throw?new?RuntimeException("test");//拋出unchecked異常,觸發(fā)事物,回滾??
  • }??
  • noRollbackFor
    [java]?view plain?copy
  • @Transactional(noRollbackFor=RuntimeException.class)??
  • ????@Override??
  • ????public?void?insert(Test?test)?{??
  • ????????dao.insert(test);??
  • ????????//拋出unchecked異常,觸發(fā)事物,noRollbackFor=RuntimeException.class,不回滾??
  • ????????throw?new?RuntimeException("test");??
  • ????}??
  • 類(lèi),當(dāng)作用于類(lèi)上時(shí),該類(lèi)的所有 public 方法將都具有該類(lèi)型的事務(wù)屬性

    [java]?view plain?copy
  • @Transactional??
  • public?class?MyBatisServiceImpl?implements?MyBatisService?{??
  • ??
  • ????@Autowired??
  • ????private?MyBatisDao?dao;??
  • ??????
  • ??????
  • ????@Override??
  • ????public?void?insert(Test?test)?{??
  • ????????dao.insert(test);??
  • ????????//拋出unchecked異常,觸發(fā)事物,回滾??
  • ????????throw?new?RuntimeException("test");??
  • ????}??
  • propagation=Propagation.NOT_SUPPORTED

    [java]?view plain?copy
  • @Transactional(propagation=Propagation.NOT_SUPPORTED)??
  • @Override??
  • public?void?insert(Test?test)?{??
  • ????//事物傳播行為是PROPAGATION_NOT_SUPPORTED,以非事務(wù)方式運(yùn)行,不會(huì)存入數(shù)據(jù)庫(kù)??
  • ????dao.insert(test);??
  • }??
    • myBatis為例 ? 基于注解的聲明式事務(wù)管理配置,xml配置

    主要為aop切面配置,只看xml就可以了

    [html]?view plain?copy
  • <!--?事物切面配置?-->??
  • <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>??
  • 總結(jié)

    以上是生活随笔為你收集整理的spring事务配置,声明式事务管理和基于@Transactional注解的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。