spring 事務詳解
來源:程序員人生 發布時間:2016-12-15 10:11:22 閱讀次數:4663次
1、甚么是事務
事務是1系列的動作,它們綜合在1起才是1個完全的工作單元,這些動作必須全部完成,如果有1個失敗的話,那末事務就會回滾到最開始的狀態。事務有4個特性ACID:
- 原子性(Atomicity):事務是1個原子操作,由1系列動作組成。事務的原子性確保動作要末全部完成,要末完全不起作用。
- 1致性(Consistency):1旦事務完成(不管成功還是失敗),系統必須確保它所建模的業務處于1致的狀態,而不會是部份完成部份失敗
- 隔離性(Isolation):可能有許多事務會同時處理相同的數據,因此每一個事務都應當與其他事務隔離開來,避免數據破壞。
- 持久性(Durability):1旦事務完成,不管產生甚么系統毛病,它的結果都不應當遭到影響。通常情況下,事務的結果被寫到持久化存儲器中。
2、spring事務管理器
Spring其實不直接收理事務,而是提供了多種事務管理器。Spring事務管理器的接口是org.springframework.transaction.PlatformTransactionManager,通過這個接口,Spring為各個平臺如JDBC、Hibernate等都提供了對應的事務管理器,但是具體的實現就是各個平臺自己的事情了。接口中有3個方法
public interface PlatformTransactionManager {
//根據事務定義TransactionDefinition,獲得事務
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
//提交事務
void commit(TransactionStatus status) throws TransactionException;
//回滾事務
void rollback(TransactionStatus status) throws TransactionException;
}
其中,TransactionDefinition是事務的1些基礎信息,如超時時間,隔離級別,傳播特性等;TransactionStatus是事務的狀態,如是否是1個新事務,是不是被標記為回滾等。Spring針對不同的ORM提供的事務管理器,都是集成自AbstractPlatformTransactionManager,而AbstractPlatformTransactionManager又實現了PlatformTransactionManager。
2.1 JDBC、Mybatis和ibatis事務管理器
如果利用程序中直接使用JDBC來進行持久化,需要配置JDBC事務管理器DataSourceTransactionManager,通過DataSource獲得到java.sql.Connection來管理事務,調用連接的commit()方法來提交事務,一樣,事務失敗則通過調用rollback()方法進行回滾。
-
<!-- (事務管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
2.2 Hibernate事務管理器 -
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
2.3 JPA事務管理器 -
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
通過entityManagerFactory屬性指定需要事務管理的javax.persistence.EntityManagerFactory對象。還需要為entityManagerFactory對象指定jpaDialect屬性,該屬性所對應的對象指定了如何獲得連接對象、開啟事務、關閉事務等事務管理相干的行動。
-
<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"/>
2.4 Java散布式事務管理器JTA -
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="jotm" />
</bean>
-
<!-- JOTM實例 -->
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean">
<property name="defaultTimeout" value="500000"/>
</bean>
散布式事務通常是指多個數據源之間的實物,在tomcat下,是沒有散布式事務的,不過可以借助于第3方軟件jotm(Java Open Transaction Manager )和AtomikosTransactionsEssentials實現。
2.5 JDO事務管理器
-
<bean id="txManager" class="org.springframework.orm.jdo.JdoTransactionManager">
<property name="persistenceManagerFactory" ref="persistenceManagerFactory"/>
</bean>
通過persistenceManagerFactory屬性指定需要事務管理的javax.jdo.PersistenceManagerFactory對象。
具體可參考:http://hhhk.iteye.com/blog/2082714
3、Spring事務的特性
1、事務的傳播行動
所謂事務的傳播行動是指,如果在開始當前事務之前,1個事務上下文已存在,此時有若干選項可以指定1個事務性方法的履行行動。在TransactionDefinition定義中包括了以下幾個表示傳播行動的常量:
-
TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則創建1個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價于TransactionDefinition.PROPAGATION_REQUIRED。
TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。
TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出異常。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:創建1個新的事務,如果當前存在事務,則把當前事務掛起。
TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建1個新的事務。這是默許值。
2、事務的隔離級別
隔離級別是指若干個并發的事務之間的隔離程度。TransactionDefinition 接口中定義了5個表示隔離級別的常量:
-
TransactionDefinition.ISOLATION_READ_UNCOMMITTED:該隔離級別表示1個事務可以讀取另外一個事務修改但還沒有提交的數據。該級別不能避免臟讀,不可重復讀和幻讀,因此很少使用該隔離級別。
TransactionDefinition.ISOLATION_READ_COMMITTED:該隔離級別表示1個事務只能讀取另外一個事務已提交的數據。該級別可以避免臟讀,這也是大多數情況下的推薦值。
TransactionDefinition.ISOLATION_REPEATABLE_READ:該隔離級別表示1個事務在全部進程中可以屢次重復履行某個查詢,并且每次返回的記錄都相同。該級別可以避免臟讀和不可重復讀。
TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事務順次逐一履行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以避免臟讀、不可重復讀和幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。
3、只讀屬性
事務的第3個特性是它是不是為只讀事務。如果事務只對后真個數據庫進行該操作,數據庫可以利用事務的只讀特性來進行1些特定的優化。
4、事務超時
由于事務可能觸及對后端數據庫的鎖定,所以長時間的事務會沒必要要的占用數據庫資源。事務超時就是事務的1個定時器,在特定時間內事務如果沒有履行終了,那末就會自動回滾,而不是1直等待其結束。
5、回滾規則
唆使spring事務管理器回滾1個事務的推薦方法是在當前事務的上下文內拋出異常。spring事務管理器會捕捉任何未處理的異常,然后根據規則決定是不是回滾拋出異常的事務。默許配置下,spring只有在拋出的異常為運行時unchecked異常時才回滾該事務,也就是拋出的異常為RuntimeException的子類(Errors也會致使事務回滾),而拋出checked異常則不會致使事務回滾。可以明確的配置在拋出那些異常時回滾事務,包括checked異常。也能夠明肯定義那些異常拋出時不回滾事務。還可以編程性的通過setRollbackOnly()方法來唆使1個事務必須回滾,在調用完setRollbackOnly()后你所能履行的唯1操作就是回滾。
6、事務狀態
public interface TransactionStatus{
boolean isNewTransaction(); // 是不是是新的事物
boolean hasSavepoint(); // 是不是有恢復點
void setRollbackOnly(); // 設置為只回滾
boolean isRollbackOnly(); // 是不是為只回滾
boolean isCompleted; // 是不是已完成
}
4、Spring支持的事務管理
Spring提供了對編程式事務和聲明式事務的支持,編程式事務允許用戶在代碼中精肯定義事務的邊界,而聲明式事務(基于AOP)有助于用戶將操作與事務規則進行解耦。
Spring配置文件中關于事務配置總是由3個組成部份,分別是DataSource、TransactionManager和代理機制這3部份,不管哪一種配置方式,1般變化的只是代理機制這部份。DataSource、TransactionManager這兩部份只是會根據數據訪問方式有所變化,比如使用Hibernate進行數據訪問時,DataSource實際為SessionFactory,TransactionManager的實現為HibernateTransactionManager。
1、編程式事務
Spring提供兩種方式的編程式事務管理,分別是:使用TransactionTemplate和直接使用PlatformTransactionManager。
1)采取TransactionTemplate和采取其他Spring模板,如JdbcTempalte和HibernateTemplate是1樣的方法,它使用回調方法,把利用程序從處理獲得和釋放資源中擺脫出來。TransactionTemplate是線程安全的。
-
<!-- JDBC事務管理器 注意:事務管理器傳的參數是數據源-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager" scope="singleton">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
<!-- 聲明事務模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
</bean>
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Error err) {
// Transactional code threw error -> rollback
rollbackOnException(status, err);
throw err;
}
catch (Exception ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}
可以看到transactionTemplate 的履行是在execute中的,所以 -
TransactionTemplate tt = new TransactionTemplate(); // 新建1個TransactionTemplate
Object result = tt.execute(
new TransactionCallback(){
public Object doTransaction(TransactionStatus status){
updateOperation();
return resultOfUpdateOperation();
}
}); // 履行execute方法進行事務管理
2)使用PlatformTransactionManager
2、聲明式事務管理
1)利用aop配置
-
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="interceptorPointCuts" expression="execution(* com.bluesky.spring.dao.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" />
</aop:config>
2)聲明式注解事務 -
<!-- 注解方式配置事物 -->
<tx:annotation-driven transaction-manager="transactionManager" />
3)使用攔截器 -
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager" />
<!-- 配置事務屬性 -->
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*Dao</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈