您好,登錄后才能下訂單哦!
這篇文章主要介紹“Spring事務的知識點有哪些”,在日常操作中,相信很多人在Spring事務的知識點有哪些問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Spring事務的知識點有哪些”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
事務首先是一系列操作組成的工作單元,該工作單元內的操作是不可分割的,即要么所有操作都做,要么所有操作都不做,這就是事務。
事務必需滿足ACID(原子性、一致性、隔離性和持久性)特性,缺一不可:
原子性(Atomicity):即事務是不可分割的最小工作單元,事務內的操作要么全做,要么全不做;
一致性(Consistency):在事務執行前數據庫的數據處于正確的狀態,而事務執行完成后數據庫的數據還是處于正確的狀態,即數據完整性約束沒有被破壞;如銀行轉帳,A轉帳給B,必須保證A的錢一定轉給B,一定不會出現A的錢轉了但B沒收到,否則數據庫的數據就處于不一致(不正確)的狀態。
隔離性(Isolation):并發事務執行之間無影響,在一個事務內部的操作對其他事務是不產生影響,這需要事務隔離級別來指定隔離性;
持久性(Durability):事務一旦執行成功,它對數據庫的數據的改變必須是永久的,不會因比如遇到系統故障或斷電造成數據不一致或丟失。
在實際項目開發中數據庫操作一般都是并發執行的,即有多個事務并發執行,并發執行就可能遇到問題,目前常見的問題如下:
丟失更新:兩個事務同時更新一行數據,最后一個事務的更新會覆蓋掉第一個事務的更新,從而導致第一個事務更新的數據丟失,這是由于沒有加鎖造成的;
臟讀:一個事務看到了另一個事務未提交的更新數據;
不可重復讀:在同一事務中,多次讀取同一數據卻返回不同的結果;也就是有其他事務更改了這些數據;
幻讀:一個事務在執行過程中讀取到了另一個事務已提交的插入數據;即在第一個事務開始時讀取到一批數據,但此后另一個事務又插入了新數據并提交,此時第一個事務又讀取這批數據但發現多了一條,即好像發生幻覺一樣。
為了解決這些并發問題,需要通過數據庫隔離級別來解決,在標準SQL規范中定義了四種隔離級別:
未提交讀(Read Uncommitted):最低隔離級別,一個事務能讀取到別的事務未提交的更新數據,很不安全,可能出現丟失更新、臟讀、不可重復讀、幻讀;
提交讀(Read Committed):一個事務能讀取到別的事務提交的更新數據,不能看到未提交的更新數據,不可能可能出現丟失更新、臟讀,但可能出現不可重復讀、幻讀;
可重復讀(Repeatable Read):保證同一事務中先后執行的多次查詢將返回同一結果,不受其他事務影響,可能可能出現丟失更新、臟讀、不可重復讀,但可能出現幻讀;
序列化(Serializable):最高隔離級別,不允許事務并發執行,而必須串行化執行,最安全,不可能出現更新、臟讀、不可重復讀、幻讀。
隔離級別越高,數據庫事務并發執行性能越差,能處理的操作越少。因此在實際項目開發中為了考慮并發性能一般使用提交讀隔離級別,它能避免丟失更新和臟讀,盡管不可重復讀和幻讀不能避免,但可以在可能出現的場合使用悲觀鎖或樂觀鎖來解決這些問題。
數據庫事務類型有本地事務和分布式事務:
本地事務:就是普通事務,能保證單臺數據庫上的操作的ACID,被限定在一臺數據庫上;
分布式事務:涉及兩個或多個數據庫源的事務,即跨越多臺同類或異類數據庫的事務(由每臺數據庫的本地事務組成的),分布式事務旨在保證這些本地事務的所有操作的ACID,使事務可以跨越多臺數據庫;
Java事務類型有JDBC事務和JTA事務:
JDBC事務:就是數據庫事務類型中的本地事務,通過Connection對象的控制來管理事務;
JTA事務:JTA指Java事務API(Java Transaction API),是Java EE數據庫事務規范, JTA只提供了事務管理接口,由應用程序服務器廠商(如WebSphere Application Server)提供實現,JTA事務比JDBC更強大,支持分布式事務。
Java EE事務類型有本地事務和全局事務:
本地事務:使用JDBC編程實現事務;
全局事務:由應用程序服務器提供,使用JTA事務;
按是否通過編程實現事務有聲明式事務和編程式事務;
聲明式事務: 通過注解或XML配置文件指定事務信息;
編程式事務:通過編寫代碼實現事務。
Spring框架最核心功能之一就是事務管理,而且提供一致的事務管理抽象,這能幫助我們:
提供一致的編程式事務管理API,不管使用Spring JDBC框架還是集成第三方框架使用該API進行事務編程;
無侵入式的聲明式事務支持。
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的時候。
默認為讀寫事務。
Spring框架支持事務管理的核心是事務管理器抽象,對于不同的數據訪問框架(如Hibernate)通過實現策略接口PlatformTransactionManager,從而能支持各種數據訪問框架的事務管理,PlatformTransactionManager接口定義如下:
java代碼:
public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }
getTransaction():返回一個已經激活的事務或創建一個新的事務(根據給定的TransactionDefinition類型參數定義的事務屬性),返回的是TransactionStatus對象代表了當前事務的狀態,其中該方法拋出TransactionException(未檢查異常)表示事務由于某種原因失敗。
commit():用于提交TransactionStatus參數代表的事務,具體語義請參考Spring Javadoc;
rollback():用于回滾TransactionStatus參數代表的事務,具體語義請參考Spring Javadoc。
TransactionDefinition接口定義如下:
java代碼:
public interface TransactionDefinition { int getPropagationBehavior(); int getIsolationLevel(); int getTimeout(); boolean isReadOnly(); String getName(); }
getPropagationBehavior():返回定義的事務傳播行為;
getIsolationLevel():返回定義的事務隔離級別;
getTimeout():返回定義的事務超時時間;
isReadOnly():返回定義的事務是否是只讀的;
getName():返回定義的事務名字。
TransactionStatus接口定義如下:
java代碼:
public interface TransactionStatus extends SavepointManager { boolean isNewTransaction(); boolean hasSavepoint(); void setRollbackOnly(); boolean isRollbackOnly(); void flush(); boolean isCompleted(); }
isNewTransaction():返回當前事務狀態是否是新事務;
hasSavepoint():返回當前事務是否有保存點;
setRollbackOnly():設置當前事務應該回滾;
isRollbackOnly(():返回當前事務是否應該回滾;
flush():用于刷新底層會話中的修改到數據庫,一般用于刷新如Hibernate/JPA的會話,可能對如JDBC類型的事務無任何影響;
isCompleted():當前事務否已經完成。
Spring提供了許多內置事務管理器實現:
DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,數據源事務管理器,提供對單個javax.sql.DataSource事務管理,用于Spring JDBC抽象框架、iBATIS或MyBatis框架的事務管理;
JdoTransactionManager:位于org.springframework.orm.jdo包中,提供對單個javax.jdo.PersistenceManagerFactory事務管理,用于集成JDO框架時的事務管理;
JpaTransactionManager:位于org.springframework.orm.jpa包中,提供對單個javax.persistence.EntityManagerFactory事務支持,用于集成JPA實現框架時的事務管理;
HibernateTransactionManager:位于org.springframework.orm.hibernate3包中,提供對單個org.hibernate.SessionFactory事務支持,用于集成Hibernate框架時的事務管理;該事務管理器只支持Hibernate3+版本,且Spring3.0+版本只支持Hibernate 3.2+版本;
JtaTransactionManager:位于org.springframework.transaction.jta包中,提供對分布式事務管理的支持,并將事務管理委托給Java EE應用服務器事務管理器;
OC4JjtaTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的對OC4J10.1.3+應用服務器事務管理器的適配器,此適配器用于對應用服務器提供的高級事務的支持;
WebSphereUowTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的對WebSphere 6.0+應用服務器事務管理器的適配器,此適配器用于對應用服務器提供的高級事務的支持;
WebLogicJtaTransactionManager:位于org.springframework.transaction.jta包中,Spring提供的對WebLogic 8.1+應用服務器事務管理器的適配器,此適配器用于對應用服務器提供的高級事務的支持。
Spring不僅提供這些事務管理器,還提供對如JMS事務管理的管理器等,Spring提供一致的事務抽象如圖9-1所示。
圖9-1 Spring事務管理器
接下來讓我們學習一下如何在Spring配置文件中定義事務管理器:
一、聲明對本地事務的支持:
a)JDBC及iBATIS、MyBatis框架事務管理器
java代碼:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
通過dataSource屬性指定需要事務管理的單個javax.sql.DataSource對象。
b)Jdo事務管理器
java代碼:
<bean id="txManager" class="org.springframework.orm.jdo.JdoTransactionManager"> <property name="persistenceManagerFactory" ref="persistenceManagerFactory"/> </bean>
通過persistenceManagerFactory屬性指定需要事務管理的javax.jdo.PersistenceManagerFactory對象。
c)Jpa事務管理器
java代碼:
bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean>
通過entityManagerFactory屬性指定需要事務管理的javax.persistence.EntityManagerFactory對象。
還需要為entityManagerFactory對象指定jpaDialect屬性,該屬性所對應的對象指定了如何獲取連接對象、開啟事務、關閉事務等事務管理相關的行為。
java代碼:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> …… <property name="jpaDialect" ref="jpaDialect"/> </bean> <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
d)Hibernate事務管理器
java代碼:
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
通過entityManagerFactory屬性指定需要事務管理的org.hibernate.SessionFactory對象。
從上節編程式實現事務管理可以深刻體會到編程式事務的痛苦,即使通過代理配置方式也是不小的工作量。
本節將介紹聲明式事務支持,使用該方式后最大的獲益是簡單,事務管理不再是令人痛苦的,而且此方式屬于無侵入式,對業務邏輯實現無影響。
接下來先來看看聲明式事務如何實現吧。
1、定義業務邏輯實現,此處使用ConfigUserServiceImpl和ConfigAddressServiceImpl:
2、定義配置文件(chapter9/service/ applicationContext-service-declare.xml):
2.1、XML命名空間定義,定義用于事務支持的tx命名空間和AOP支持的aop命名空間:
java代碼: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
2.2、業務實現配置,非常簡單,使用以前定義的非侵入式業務實現:
java代碼: <bean id="userService" class="cn.javass.spring.chapter9.service.impl.ConfigUserServiceImpl"> <property name="userDao" ref="userDao"/> <property name="addressService" ref="addressService"/> </bean> <bean id="addressService" class="cn.javass.spring.chapter9.service.impl.ConfigAddressServiceImpl"> <property name="addressDao" ref="addressDao"/> </bean>
2.3、事務相關配置:
java代碼: <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED"/> <tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED" read-only="true"/> </tx:attributes> </tx:advice>
java代碼:
<tx:advice>:事務通知定義,用于指定事務屬性,其中“transaction-manager”屬性指定事務管理器,并通過< tx:attributes >指定具體需要攔截的方法; <tx:method name=”save*”>:表示將攔截以save開頭的方法,被攔截的方法將應用配置的事務屬性:propagation=”REQUIRED”表示傳播行為是Required,isolation=”READ_COMMITTED”表示隔離級別是提交讀; <tx:method name=”*”>:表示將攔截其他所有方法,被攔截的方法將應用配置的事務屬性:propagation=”REQUIRED”表示傳播行為是Required,isolation=”READ_COMMITTED”表示隔離級別是提交讀,read-only=”true”表示事務只讀; :AOP相關配置: :切入點定義,定義名為”serviceMethod”的aspectj切入點,切入點表達式為”execution(* cn..chapter9.service..*.*(..))”表示攔截cn包及子包下的chapter9\. service包及子包下的任何類的任何方法; :Advisor定義,其中切入點為serviceMethod,通知為txAdvice。 從配置中可以看出,將對cn包及子包下的chapter9\. service包及子包下的任何類的任何方法應用“txAdvice”通知指定的事務屬性。
3、修改測試方法并測試該配置方式是否好用:
將TransactionTest 類的testServiceTransaction測試方法拷貝一份命名為testDeclareTransaction:
并在testDeclareTransaction測試方法內將:
4、執行測試,測試正常通過,說明該方式能正常工作,當調用save方法時將匹配到事務通知中定義的“
聲明式事務是如何實現事務管理的呢?還記不記得TransactionProxyFactoryBean實現配置式事務管理,配置式事務管理是通過代理方式實現,而聲明式事務管理同樣是通過AOP代理方式實現。
聲明式事務通過AOP代理方式實現事務管理,利用環繞通知TransactionInterceptor實現事務的開啟及關閉,而TransactionProxyFactoryBean內部也是通過該環繞通知實現的,因此可以認為是
了解了實現方式后,接下來詳細學習一下配置吧:
9.4.4
聲明式事務管理通過配置
java代碼: <tx:advice id="……" transaction-manager="……"> <tx:attributes> <tx:method name="……" propagation=" REQUIRED" isolation="READ_COMMITTED" timeout="-1" read-only="false" no-rollback-for="" rollback-for=""/> …… </tx:attributes> </tx:advice> <tx:advice>:id用于指定此通知的名字, transaction-manager用于指定事務管理器,默認的事務管理器名字為“transactionManager”; <tx:method>:用于定義事務屬性即相關聯的方法名;
name:定義與事務屬性相關聯的方法名,將對匹配的方法應用定義的事務屬性,可以使用“”通配符來匹配一組或所有方法,如“save”將匹配以save開頭的方法,而“*”將匹配所有方法;
propagation:事務傳播行為定義,默認為“REQUIRED”,表示Required,其值可以通過TransactionDefinition的靜態傳播行為變量的“PROPAGATION_”后邊部分指定,如“TransactionDefinition.PROPAGATION_REQUIRED”可以使用“REQUIRED”指定;
isolation:事務隔離級別定義;默認為“DEFAULT”,其值可以通過TransactionDefinition的靜態隔離級別變量的“ISOLATION_”后邊部分指定,如“TransactionDefinition. ISOLATION_DEFAULT”可以使用“DEFAULT”指定:
timeout:事務超時時間設置,單位為秒,默認-1,表示事務超時將依賴于底層事務系統;
read-only:事務只讀設置,默認為false,表示不是只讀;
rollback-for:需要觸發回滾的異常定義,以“,”分割,默認任何RuntimeException 將導致事務回滾,而任何Checked Exception 將不導致事務回滾;異常名字定義和TransactionProxyFactoryBean中含義一樣
no-rollback-for:不被觸發進行回滾的 Exception(s);以“,”分割;異常名字定義和TransactionProxyFactoryBean中含義一樣;
記不記得在配置方式中為了解決“自我調用”而導致的不能設置正確的事務屬性問題,使用“((IUserService)AopContext.currentProxy()).otherTransactionMethod()”方式解決,在聲明式事務要得到支持需要使用來開啟。
9.4.5 多事務語義配置及最佳實踐
什么是多事務語義?說白了就是為不同的Bean配置不同的事務屬性,因為我們項目中不可能就幾個Bean,而可能很多,這可能需要為Bean分組,為不同組的Bean配置不同的事務語義。在Spring中,可以通過配置多切入點和多事務通知并通過不同方式組合使用即可。
1、首先看下聲明式事務配置的最佳實踐吧: <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="create*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="merge*" propagation="REQUIRED" /> <tx:method name="del*" propagation="REQUIRED" /> <tx:method name="remove*" propagation="REQUIRED" /> <tx:method name="put*" propagation="REQUIRED" /> <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> <tx:method name="count*" propagation="SUPPORTS" read-only="true" /> <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> <tx:method name="list*" propagation="SUPPORTS" read-only="true" /> <tx:method name="*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice>
該聲明式事務配置可以應付常見的CRUD接口定義,并實現事務管理,我們只需修改切入點表達式來攔截我們的業務實現從而對其應用事務屬性就可以了,如果還有更復雜的事務屬性直接添加即可,即
如果我們有一個batchSaveOrUpdate方法需要“REQUIRES_NEW”事務傳播行為,則直接添加如下配置即可:
java代碼:
1
2、接下來看一下多事務語義配置吧,聲明式事務最佳實踐中已經配置了通用事務屬性,因此可以針對需要其他事務屬性的業務方法進行特例化配置:
java代碼: <tx:advice id="noTxAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="*" propagation="NEVER" /> </tx:attributes> </tx:advice>
該聲明將對切入點匹配的方法所在事務應用“Never”傳播行為。
多事務語義配置時,切入點一定不要疊加,否則將應用兩次事務屬性,造成不必要的錯誤及麻煩。
對聲明式事務管理,Spring提供基于 @Transactional注解方式來實現,但需要Java 5+。
注解方式是最簡單的事務配置方式,可以直接在Java源代碼中聲明事務屬性,且對于每一個業務類或方法如果需要事務都必須使用此注解。
接下來學習一下注解事務的使用吧:
1、定義業務邏輯實現:
package cn.javass.spring.chapter9.service.impl; //省略import public class AnnotationUserServiceImpl implements IUserService { private IUserDao userDao; private IAddressService addressService; public void setUserDao(IUserDao userDao) { this.userDao = userDao; } public void setAddressService(IAddressService addressService) { this.addressService = addressService; } @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED) @Override public void save(final UserModel user) { userDao.save(user); user.getAddress().setUserId(user.getId()); addressService.save(user.getAddress()); } @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, readOnly=true) @Override public int countAll() { return userDao.countAll(); } }
2、定義配置文件(chapter9/service/ applicationContext-service-annotation.xml):
2.1、XML命名空間定義,定義用于事務支持的tx命名空間和AOP支持的aop命名空間:
java代碼:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
2.2、業務實現配置,非常簡單,使用以前定義的非侵入式業務實現:
java代碼: <bean id="userService" class="cn.javass.spring.chapter9.service.impl.ConfigUserServiceImpl"> <property name="userDao" ref="userDao"/> <property name="addressService" ref="addressService"/> </bean> <bean id="addressService" class="cn.javass.spring.chapter9.service.impl.ConfigAddressServiceImpl"> <property name="addressDao" ref="addressDao"/> </bean>
2.3、事務相關配置:
java代碼: 1 <tx:annotation-driven transaction-manager="txManager"/> 使用如上配置已支持聲明式事務。 3、修改測試方法并測試該配置方式是否好用: 將TransactionTest 類的testServiceTransaction測試方法拷貝一份命名為testAnntationTransactionTest: classpath:chapter9/service/applicationContext-service-annotation.xml" userService.save(user); try { userService.save(user); Assert.fail(); } catch (RuntimeException e) { } Assert.assertEquals(0, userService.countAll()); Assert.assertEquals(0, addressService.countAll());
4、執行測試,測試正常通過,說明該方式能正常工作,因為在AnnotationAddressServiceImpl類的save方法中拋出異常,因此事務需要回滾,所以兩個countAll操作都返回0。
9.4.7
@Transactional配置詳解
Spring提供的
transaction-manager:指定事務管理器名字,默認為transactionManager,當使用其他名字時需要明確指定;
proxy-target-class:表示將使用的代碼機制,默認false表示使用JDK代理,如果為true將使用CGLIB代理
order:定義事務通知順序,默認Ordered.LOWEST_PRECEDENCE,表示將順序決定權交給AOP來處理。
Spring使用
@Transactional 來指定事務屬性,可以在接口、類或方法上指定,如果類和方法上都指定了
@Transactional ,則方法上的事務屬性被優先使用,具體屬性如下:
value:指定事務管理器名字,默認使用
propagation:指定事務傳播行為,默認為Required,使用Propagation.REQUIRED指定;
isolation:指定事務隔離級別,默認為“DEFAULT”,使用Isolation.DEFAULT指定;
readOnly:指定事務是否只讀,默認false表示事務非只讀;
timeout:指定事務超時時間,以秒為單位,默認-1表示事務超時將依賴于底層事務系統;
rollbackFor:指定一組異常類,遇到該類異常將回滾事務;
rollbackForClassname:指定一組異常類名字,其含義與
noRollbackFor:指定一組異常類,即使遇到該類異常也將提交事務,即不回滾事務;
noRollbackForClassname:指定一組異常類名字,其含義與
Spring提供的
@Transactional 注解事務管理內部同樣利用環繞通知TransactionInterceptor實現事務的開啟及關閉。
使用 @Transactional注解事務管理需要特別注意以下幾點:
如果在接口、實現類或方法上都指定了
@Transactional 注解,則優先級順序為方法>實現類>接口;
建議只在實現類或實現類的方法上使用
@Transactional,而不要在接口上使用,這是因為如果使用JDK代理機制是沒問題,因為其使用基于接口的代理;而使用使用CGLIB代理機制時就會遇到問題,因為其使用基于類的代理而不是接口,這是因為接口上的
@Transactional注解是“不能繼承的”;
具體請參考基于JDK動態代理和CGLIB動態代理的實現Spring注解管理事務(@Trasactional)到底有什么區別。
在Spring代理機制下(不管是JDK動態代理還是CGLIB代理),“自我調用”同樣不會應用相應的事務屬性,其語義和
默認只對RuntimeException異常回滾;
在使用Spring代理時,默認只有在public可見度的方法的
@Transactional 注解才是有效的,其它可見度(protected、private、包可見)的方法上即使有
@Transactional
注解也不會應用這些事務屬性的,Spring也不會報錯,如果你非要使用非公共方法注解事務管理的話,可考慮使用AspectJ。
到此,關于“Spring事務的知識點有哪些”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。