本篇內(nèi)容主要講解“spring中的事務(wù)是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“spring中的事務(wù)是什么”吧!
成都創(chuàng)新互聯(lián)公司主營(yíng)澄海網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,成都APP應(yīng)用開發(fā),澄海h5微信小程序開發(fā)搭建,澄海網(wǎng)站營(yíng)銷推廣歡迎澄海等地區(qū)企業(yè)咨詢
1)spring的事務(wù)管理器:
package org.springframework.transaction; public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }
2)spring的事務(wù)定義類:
package org.springframework.transaction; import java.sql.Connection; public interface TransactionDefinition { // 事務(wù)的傳播行為 int PROPAGATION_REQUIRED = 0; // 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。這是默認(rèn)值。 int PROPAGATION_SUPPORTS = 1; // 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。 int PROPAGATION_MANDATORY = 2; // 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常。 int PROPAGATION_REQUIRES_NEW = 3; // 創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。 int PROPAGATION_NOT_SUPPORTED = 4; // 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。 int PROPAGATION_NEVER = 5; // 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。 int PROPAGATION_NESTED = 6; // 如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運(yùn)行;如果當(dāng)前沒有事務(wù),則等價(jià)于PROPAGATION_REQUIRED。 // 事務(wù)的隔離級(jí)別 int ISOLATION_DEFAULT = -1; // 使用底層數(shù)據(jù)庫的默認(rèn)隔離級(jí)別。 int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED; int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED; int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ; int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE; /** * Use the default timeout of the underlying transaction system, or none if timeouts are not supported. */ // 事務(wù)超時(shí):指一個(gè)事務(wù)所允許執(zhí)行的最長(zhǎng)時(shí)間,如果超過該時(shí)間限制但事務(wù)還沒有完成,則自動(dòng)回滾事務(wù)。 // 默認(rèn)為底層事務(wù)系統(tǒng)的超時(shí)值,如果底層數(shù)據(jù)庫事務(wù)系統(tǒng)沒有設(shè)置超時(shí)值,那么就是none,沒有超時(shí)限制。 int TIMEOUT_DEFAULT = -1; int getPropagationBehavior(); int getIsolationLevel(); int getTimeout(); boolean isReadOnly(); String getName(); }
3)spring中事務(wù)的回滾:
1)spring推薦以拋出異常的方式來回滾一個(gè)事務(wù)。 2)spring事務(wù)管理器會(huì)捕捉任何未處理的異常,然后根據(jù)相應(yīng)的配置來判斷是否回滾拋出異常的事務(wù)。 1>默認(rèn)配置下,spring只有在拋出的異常為運(yùn)行時(shí)unchecked異常時(shí)才回滾該事務(wù),也就是拋出的異常為RuntimeException的子類(Errors也會(huì)導(dǎo)致事務(wù)回滾),而拋出checked異常則不會(huì)導(dǎo)致事務(wù)回滾。 2>可以配置在拋出哪些異常時(shí)回滾事務(wù),包括checked異常;也可以明確設(shè)置哪些異常拋出時(shí)不回滾事務(wù)。
4)@Transactional注解
屬性 類型 描述 value String 可選的限定描述符,指定使用的事務(wù)管理器 propagation enum 可選的事務(wù)傳播行為設(shè)置 isolation enum 可選的事務(wù)隔離級(jí)別設(shè)置 readOnly boolean 讀寫或只讀事務(wù),默認(rèn)讀寫 timeout int (in seconds granularity)事務(wù)超時(shí)時(shí)間設(shè)置 rollbackFor (繼承Throwable的)Class數(shù)組 導(dǎo)致事務(wù)回滾的異常類數(shù)組 rollbackForClassName (繼承Throwable的)類名數(shù)組 導(dǎo)致事務(wù)回滾的異常類名字?jǐn)?shù)組 noRollbackFor (繼承Throwable的)Class數(shù)組 不會(huì)導(dǎo)致事務(wù)回滾的異常類數(shù)組 noRollbackForClassName (繼承Throwable的)類名數(shù)組 不會(huì)導(dǎo)致事務(wù)回滾的異常類名字?jǐn)?shù)組 用法:可以寫在類(接口)上,也可以方法上。 1)當(dāng)作用于類上時(shí),該類的所有public方法將都具有該類型的事務(wù)屬性。 2)可以在方法上使用該注解來覆蓋類級(jí)別上的設(shè)置。 3)Spring建議不要在接口或接口方法上使用該注解,因?yàn)橹挥性谑褂没诮涌诘拇頃r(shí)它才會(huì)生效。 4)在private、protected、default的方法上使用該注解,則該注解將被忽略,也不會(huì)拋出任何異常。 5)默認(rèn)情況下,只有來自外部的方法調(diào)用才會(huì)被AOP代理捕獲,也就是說:類內(nèi)部方法調(diào)用本類內(nèi)部的其它方法并不會(huì)引起事務(wù)行為,即使被調(diào)用方法使用@Transactional注解進(jìn)行修飾!
5)原理:
1)spring的事務(wù)管理是通過spring的AOP(動(dòng)態(tài)代理)來實(shí)現(xiàn)的。 spring中事務(wù)生效的一個(gè)前提:調(diào)用的方法必須被TransactionInterceptor攔截。 說明:只有通過TransactionInterceptor攔截的方法才會(huì)被加入到spring的事務(wù)管理中。 舉例: 在方法A中調(diào)用@Transactional修飾的方法B時(shí),如果方法A與方法B在同一個(gè)類TestClass中,則加在方法B上的@Transactional注解不起作用,因?yàn)榇藭r(shí)方法A對(duì)方法B的調(diào)用是不會(huì)被攔截器攔截的! 解決辦法:在方法A中,使用當(dāng)前的代理對(duì)象來調(diào)用方法B。eg:((TestClass)AopContext.currentProxy()).B(); 2)對(duì)于正常的事務(wù)管理,必須關(guān)閉數(shù)據(jù)庫的自動(dòng)提交模式,spring會(huì)將底層連接的自動(dòng)提交特性設(shè)置為false。 package org.springframework.jdbc.datasource; public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean { private DataSource dataSource; /** * This implementation sets the isolation level but ignores the timeout. */ [@Override](https://my.oschina.net/u/1162528) protected void doBegin(Object transaction, TransactionDefinition definition) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; Connection con = null; try { if (txObject.getConnectionHolder() == null || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { Connection newCon = this.dataSource.getConnection(); if (logger.isDebugEnabled()) { logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); } txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); // 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); // 【spring將底層連接的自動(dòng)提交設(shè)置為false】 } txObject.getConnectionHolder().setTransactionActive(true); int timeout = determineTimeout(definition); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { txObject.getConnectionHolder().setTimeoutInSeconds(timeout); } // Bind the session holder to the thread. if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder()); } } catch (Throwable ex) { DataSourceUtils.releaseConnection(con, this.dataSource); throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); } } }
6)配置文件:
1)注解的形式: spring + mybatis: 說明:mybatis會(huì)自動(dòng)參與到spring事務(wù)的管理中,無需額外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的數(shù)據(jù)源與DataSourceTransactionManager引用的數(shù)據(jù)源一致即可,否則事務(wù)管理不起作用。 <!-- 定義事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 使用注解的形式管理事務(wù) --> <tx:annotation-driven transaction-manager="transactionManager" /> <!-- 定義SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:/mybatis_advertise.xml" /> </bean> spring + hibernate: <!-- 事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 使用注解的形式管理事務(wù) --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 定義SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:hibernate.cfg.xml" /> </bean> 2)切面的形式: <!-- 定義事務(wù)管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 事務(wù)的處理策略:相當(dāng)于注解形式中的@Transactional注解 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 設(shè)置事務(wù)的屬性,相當(dāng)于@Transactional注解的屬性 --> <tx:method name="query*" read-only="true" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="*" /> </tx:attributes> </tx:advice> <aop:config> <!--定義需要使用事務(wù)的切入點(diǎn) --> <aop:pointcut id="myPointcut" expression="execution(* com.jxn.mybatis.service.*.*(..))" /> <!--將事務(wù)的處理策略應(yīng)用到指定的切入點(diǎn) --> <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" /> </aop:config>
到此,相信大家對(duì)“spring中的事務(wù)是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
網(wǎng)站欄目:spring中的事務(wù)是什么
標(biāo)題鏈接:http://jinyejixie.com/article20/jjhhco.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)公司、動(dòng)態(tài)網(wǎng)站、面包屑導(dǎo)航、定制網(wǎng)站、網(wǎng)站建設(shè)、網(wǎng)站策劃
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)