溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

事務的回滾五種方法

發(fā)布時間:2020-07-22 09:19:29 來源:網(wǎng)絡 閱讀:1641 作者:淺嫣 欄目:開發(fā)技術

前段時間對Spring的事務配置做了比較深入的研究,在此之間對Spring的事務配置雖說也配置過,但是一直沒有一個清楚的認識。通過這次的學習發(fā)覺Spring的事務配置只要把思路理清,還是比較好掌握的。

    總結(jié)如下:
    Spring配置文件中關于事務配置總是由三個組成部分,分別是DataSource、TransactionManager和代理機制這三部分,無論哪種配置方式,一般變化的只是代理機制這部分。
    DataSource、TransactionManager這兩部分只是會根據(jù)數(shù)據(jù)訪問方式有所變化,比如使用Hibernate進行數(shù)據(jù)訪問時,DataSource實際為SessionFactory,TransactionManager的實現(xiàn)為HibernateTransactionManager。
    具體如下圖:

根據(jù)代理機制的不同,總結(jié)了五種Spring事務的配置方式,配置文件如下:
    第一種方式:每個Bean都有一個代理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    <bean id="sessionFactory"
            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocation" value="classpath:hibernate.cfg.xml" />
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
    </bean>
    <!-- 定義事務管理器(聲明式的事務) -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
  
    <!-- 配置DAO -->
    <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
  
    <bean id="userDao"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
           <!-- 配置事務管理器 -->
           <property name="transactionManager" ref="transactionManager" />   
        <property name="target" ref="userDaoTarget" />
         <property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao" />
        <!-- 配置事務屬性 -->
        <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean> 
</beans>
    第二種方式:所有Bean共享一個代理基類
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    <bean id="sessionFactory"
            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocation" value="classpath:hibernate.cfg.xml" />
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
    </bean>
    <!-- 定義事務管理器(聲明式的事務) -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
  
    <bean id="transactionBase"
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
            lazy-init="true" abstract="true">
        <!-- 配置事務管理器 -->
        <property name="transactionManager" ref="transactionManager" />
        <!-- 配置事務屬性 -->
        <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>  
 
    <!-- 配置DAO -->
    <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
  
    <bean id="userDao" parent="transactionBase" >
        <property name="target" ref="userDaoTarget" /> 
    </bean>
</beans>
 
 
 
第三種方式:使用攔截器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    <bean id="sessionFactory"
            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocation" value="classpath:hibernate.cfg.xml" />
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
    </bean>
    <!-- 定義事務管理器(聲明式的事務) -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
 
    <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>
 
    <!-- 配置DAO -->
    <bean id="userDao" class="com.bluesky.spring.dao.UserDaoImpl">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
</beans>
第四種方式:使用tx標簽配置的攔截器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    <context:annotation-config />
    <context:component-scan base-package="com.bluesky" />
    <bean id="sessionFactory"
            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocation" value="classpath:hibernate.cfg.xml" />
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
    </bean>
    <!-- 定義事務管理器(聲明式的事務) -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    <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>    
</beans>
 
第五種方式:全注解
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    <context:annotation-config />
    <context:component-scan base-package="com.bluesky" />
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="sessionFactory"
            class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="configLocation" value="classpath:hibernate.cfg.xml" />
        <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
    </bean>
    <!-- 定義事務管理器(聲明式的事務) -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
  
</beans>
 
 
package com.bluesky.spring.dao;
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Component;
import com.bluesky.spring.domain.User;
@Transactional
@Component("userDao")
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
    public List<User> listUsers() {
        return this.getSession().createQuery("from User").list();
    }
  
   
}
 
 
 
 
 
注意的幾點:
1、@Transactional只能被應用到public方法上,對于其他非public的方法,如果標記了@Transactional也不會報錯,但方法沒有事務功能。
2、默認情況下,一個有事務方法,遇到RuntimeException時會回滾,遇到受檢查的異常是不會回滾的。要想所有異常都回滾,要加上@Transactional(rollbackFor={Exception.class, 其他異常})。
 
Transactional的所有可選屬性如下:
屬性                                      類型                          默認值                     說明
propagation                   Propagation枚舉           REQUIRED       事務傳播屬性(下有說明)
isolation                         isolation枚舉                 DEFAULT         事務隔離級別(另有說明)
readOnly                      boolean                           false               是否只讀
timeout                           int                                   -1                 超時(秒)
rollbackFor                   Class[]                               {}                   需要回滾的異常類
rollbackForClassName      String[]                          {}                 需要回滾的異常類名
noRollbackFor             Class[]                                   {}               不需要回滾的異常類
noRollbackForClassName    String[]                  {}             不需要回滾的異常類名
 
事務的隔離級別  有如下可選:
可以去看spring的源代碼:org.springframework.transaction.annotation.Isolation
DEFAULT                   采用數(shù)據(jù)庫默認隔離級別
READ_UNCOMMITTED
READ_COMMITTED
REPEATABLE__READ
SERIALIZABLE
 
事務的傳播屬性,有如下可選:
可以去看spring的源代碼:org.springframework.transaction.annotation.Propagation
REQUIRED:業(yè)務方法需要在一個事務中運行,如果方法運行時,已處在一個事務中,那么就加入該事務,否則自己創(chuàng)建一個新的事物,這是spring默認的傳播行為。
SUPPORTS:如果業(yè)務方法在某個事物范圍內(nèi)被調(diào)用,則方法成為該事務的一部分,如果業(yè)務方法在事務范圍外被 調(diào)用,則方法在沒有事務的環(huán)境下執(zhí)行。
MANDATORY:只能在一個已存在事務中執(zhí)行,業(yè)務方法不能發(fā)起自己的事物,如果業(yè)務方法在沒有事務的環(huán)境下調(diào)用,就拋異常。
REQUIRES_NEW:業(yè)務方法總是會為自己發(fā)起一個新的事務,如果方法已運行在一個事務中,則原有方法被掛起, 新的事務被創(chuàng)建,直到方法結(jié)束,新事務才結(jié)束,原先的事務才會恢復執(zhí)行。
NOT_SUPPORTED:聲明方法需要事務,如果方法沒有關聯(lián)到一個事務,容器不會為他開啟事務,如果方法在一個事務中被調(diào)用,該事務會被掛起,在方法調(diào)用結(jié)束后,原先的事務便會恢復執(zhí)行。
NEVER:聲明方法絕對不能在事務范圍內(nèi)執(zhí)行,如果方法在某個事務范圍內(nèi)執(zhí)行,容器就拋異常,只有沒關聯(lián)到 事務,才正常執(zhí)行。
NESTED:如果一個活動的事務存在,則運行在一個嵌套的事務中,如果沒有活動的事務,則按REQUIRED屬性執(zhí) 行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的保證點,內(nèi)部事務回滾不會對外部事務造 成影響,它只對DataSource。
 

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI