您好,登錄后才能下訂單哦!
本篇內容主要講解“spring中的事務是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“spring中的事務是什么”吧!
1)spring的事務管理器:
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的事務定義類:
package org.springframework.transaction; import java.sql.Connection; public interface TransactionDefinition { // 事務的傳播行為 int PROPAGATION_REQUIRED = 0; // 如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。這是默認值。 int PROPAGATION_SUPPORTS = 1; // 如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。 int PROPAGATION_MANDATORY = 2; // 如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。 int PROPAGATION_REQUIRES_NEW = 3; // 創建一個新的事務,如果當前存在事務,則把當前事務掛起。 int PROPAGATION_NOT_SUPPORTED = 4; // 以非事務方式運行,如果當前存在事務,則把當前事務掛起。 int PROPAGATION_NEVER = 5; // 以非事務方式運行,如果當前存在事務,則拋出異常。 int PROPAGATION_NESTED = 6; // 如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則等價于PROPAGATION_REQUIRED。 // 事務的隔離級別 int ISOLATION_DEFAULT = -1; // 使用底層數據庫的默認隔離級別。 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. */ // 事務超時:指一個事務所允許執行的最長時間,如果超過該時間限制但事務還沒有完成,則自動回滾事務。 // 默認為底層事務系統的超時值,如果底層數據庫事務系統沒有設置超時值,那么就是none,沒有超時限制。 int TIMEOUT_DEFAULT = -1; int getPropagationBehavior(); int getIsolationLevel(); int getTimeout(); boolean isReadOnly(); String getName(); }
3)spring中事務的回滾:
1)spring推薦以拋出異常的方式來回滾一個事務。 2)spring事務管理器會捕捉任何未處理的異常,然后根據相應的配置來判斷是否回滾拋出異常的事務。 1>默認配置下,spring只有在拋出的異常為運行時unchecked異常時才回滾該事務,也就是拋出的異常為RuntimeException的子類(Errors也會導致事務回滾),而拋出checked異常則不會導致事務回滾。 2>可以配置在拋出哪些異常時回滾事務,包括checked異常;也可以明確設置哪些異常拋出時不回滾事務。
4)@Transactional注解
屬性 類型 描述 value String 可選的限定描述符,指定使用的事務管理器 propagation enum 可選的事務傳播行為設置 isolation enum 可選的事務隔離級別設置 readOnly boolean 讀寫或只讀事務,默認讀寫 timeout int (in seconds granularity)事務超時時間設置 rollbackFor (繼承Throwable的)Class數組 導致事務回滾的異常類數組 rollbackForClassName (繼承Throwable的)類名數組 導致事務回滾的異常類名字數組 noRollbackFor (繼承Throwable的)Class數組 不會導致事務回滾的異常類數組 noRollbackForClassName (繼承Throwable的)類名數組 不會導致事務回滾的異常類名字數組 用法:可以寫在類(接口)上,也可以方法上。 1)當作用于類上時,該類的所有public方法將都具有該類型的事務屬性。 2)可以在方法上使用該注解來覆蓋類級別上的設置。 3)Spring建議不要在接口或接口方法上使用該注解,因為只有在使用基于接口的代理時它才會生效。 4)在private、protected、default的方法上使用該注解,則該注解將被忽略,也不會拋出任何異常。 5)默認情況下,只有來自外部的方法調用才會被AOP代理捕獲,也就是說:類內部方法調用本類內部的其它方法并不會引起事務行為,即使被調用方法使用@Transactional注解進行修飾!
5)原理:
1)spring的事務管理是通過spring的AOP(動態代理)來實現的。 spring中事務生效的一個前提:調用的方法必須被TransactionInterceptor攔截。 說明:只有通過TransactionInterceptor攔截的方法才會被加入到spring的事務管理中。 舉例: 在方法A中調用@Transactional修飾的方法B時,如果方法A與方法B在同一個類TestClass中,則加在方法B上的@Transactional注解不起作用,因為此時方法A對方法B的調用是不會被攔截器攔截的! 解決辦法:在方法A中,使用當前的代理對象來調用方法B。eg:((TestClass)AopContext.currentProxy()).B(); 2)對于正常的事務管理,必須關閉數據庫的自動提交模式,spring會將底層連接的自動提交特性設置為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將底層連接的自動提交設置為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會自動參與到spring事務的管理中,無需額外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的數據源與DataSourceTransactionManager引用的數據源一致即可,否則事務管理不起作用。 <!-- 定義事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 使用注解的形式管理事務 --> <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: <!-- 事務管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 使用注解的形式管理事務 --> <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)切面的形式: <!-- 定義事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 事務的處理策略:相當于注解形式中的@Transactional注解 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 設置事務的屬性,相當于@Transactional注解的屬性 --> <tx:method name="query*" read-only="true" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="*" /> </tx:attributes> </tx:advice> <aop:config> <!--定義需要使用事務的切入點 --> <aop:pointcut id="myPointcut" expression="execution(* com.jxn.mybatis.service.*.*(..))" /> <!--將事務的處理策略應用到指定的切入點 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" /> </aop:config>
到此,相信大家對“spring中的事務是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。