Spring入門——事務(wù)管理Transaction Manager

最近有個朋友去面試JAVA,問了我spring事務(wù)的事情,雖然之前有學(xué)過,但是沒有融會貫通,回答得很淺。這幾天重新學(xué)習(xí)研究了下,結(jié)合《Spring實(shí)戰(zhàn)》和網(wǎng)上關(guān)于spring事務(wù)的博客文章,總結(jié)一下。

參考文章:

Spring事務(wù)管理(詳解+實(shí)例)

Spring事務(wù)配置的五種方式

Spring事務(wù)管理及幾種簡單的實(shí)現(xiàn)

Spring中事務(wù)控制的 API介紹

1、事務(wù)初識

事務(wù)是邏輯上的一組操作,要么全部成功,要么全部失敗。

事務(wù)具有ACID特性,參考百度百科,具體如下:

原子性(Atomicity):整個事務(wù)中的所有操作,要么全部完成,要么全部不完成,不可能停滯在中間某個環(huán)節(jié)。

一致性(Consistency):事務(wù)必須始終保持系統(tǒng)處于一致的狀態(tài),不管在任何給定的時間并發(fā)事務(wù)有多少。

隔離性(Isolation):隔離狀態(tài)執(zhí)行事務(wù),使它們好像是系統(tǒng)在給定時間內(nèi)執(zhí)行的唯一操作。

持久性(Durability):在事務(wù)完成以后,該事務(wù)對數(shù)據(jù)庫所作的更改便持久的保存在數(shù)據(jù)庫之中,并不會被回滾。

2、核心接口API

image

如上圖,Spring事務(wù)管理高層抽象主要有3個:

PlatformTransactionManager :事務(wù)管理器(用來管理事務(wù),包含事務(wù)的提交,回滾)

TransactionDefinition :事務(wù)定義信息(隔離,傳播,超時,只讀)

TransactionStatus :事務(wù)具體運(yùn)行狀態(tài)

2.1 PlatformTransactionManager核心事務(wù)管理器

是Spring的事務(wù)管理器核心接口。

Spring本身并不支持事務(wù)實(shí)現(xiàn),只是負(fù)責(zé)包裝底層事務(wù),應(yīng)用底層支持什么樣的事務(wù)策略,Spring就支持什么樣的事務(wù)策略。

里面提供了常用的操作事務(wù)的方法:

TransactionStatus getTransaction(TransactionDefinition definition):獲取事務(wù)狀態(tài)信息

void commit(TransactionStatus status):提交事務(wù)

void rollback(TransactionStatus status):回滾事務(wù)


Public interface PlatformTransactionManager()...{

    // 由TransactionDefinition得到TransactionStatus對象

    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

    // 提交

    Void commit(TransactionStatus status) throws TransactionException; 

    // 回滾

    Void rollback(TransactionStatus status) throws TransactionException; 

    }

2.1.1 JDBC事務(wù)

<bean id="transactionManager" class="org.springframework.jdbc.datasourceTransactionManager">    

    <property name="dataSource" ref="dataSource"/>

</bean>

DataSource TransactionManager:使用JDBC和iBatis進(jìn)行持久化數(shù)據(jù)時使用

2.1.2 Hibernate事務(wù)

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

    <property name="sessionFactory" ref="sessionFactory" />

</bean>

Hibernate TransactionManager:使用Hibernate 3.0進(jìn)行持久化數(shù)據(jù)時使用

2.1.3 Java持久化API事務(wù)(JPA)

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

    <property name="sessionFactory" ref="sessionFactory" />

</bean>

JpaTransactionManager:使用JPA進(jìn)行持久化時使用

2.1.4 Java原生API事務(wù)

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">

    <property name="transactionManagerName" value="java:/TransactionManager" />

</bean>

JtaTransactionManager :如果沒有使用上述的事務(wù)管理,或者在一個事務(wù)跨越多個事務(wù)管理源時使用

2.2 TransactionDefinition信息對象

該接口定義了一些基本事務(wù)屬性

public interface TransactionDefinition {
    int getPropagationBehavior(); // 返回事務(wù)的傳播行為
    int getIsolationLevel(); // 返回事務(wù)的隔離級別,事務(wù)管理器根據(jù)它來控制另外一個事務(wù)可以看到本事務(wù)內(nèi)的哪些數(shù)據(jù)
    int getTimeout();  // 返回事務(wù)必須在多少秒內(nèi)完成
    boolean isReadOnly(); // 事務(wù)是否只讀,事務(wù)管理器能夠根據(jù)這個返回值進(jìn)行優(yōu)化,確保事務(wù)是只讀的
} 

2.3 TransactionStatus運(yùn)行狀態(tài)

該接口定義了事務(wù)具體的運(yùn)行狀態(tài)

public interface TransactionStatus{
    boolean isNewTransaction(); // 是否是新的事物
    boolean hasSavepoint(); // 是否有恢復(fù)點(diǎn)
    void setRollbackOnly();  // 設(shè)置為只回滾
    boolean isRollbackOnly(); // 是否為只回滾
    boolean isCompleted; // 是否已完成
} 

3、編程式事務(wù)

3.1 編程式和聲明式事務(wù)的區(qū)別

Spring提供了對編程式事務(wù)和聲明式事務(wù)的支持,編程式事務(wù)允許用戶在代碼中精確定義事務(wù)的邊界,而聲明式事務(wù)(基于AOP)有助于用戶將操作與事務(wù)規(guī)則進(jìn)行解耦。
簡單地說,編程式事務(wù)侵入到了業(yè)務(wù)代碼里面,但是提供了更加詳細(xì)的事務(wù)管理;而聲明式事務(wù)由于基于AOP,所以既能起到事務(wù)管理的作用,又可以不影響業(yè)務(wù)代碼的具體實(shí)現(xiàn)。

3.2 如何實(shí)現(xiàn)編程式事務(wù)?

spring提供了兩種編程式事務(wù)管理,分別是使用TransactionTemplate和使用PlatformTransactionManager。

3.2.1 使用TransactionTemplate

采用TransactionTemplate和采用其他Spring模板一樣,使用回調(diào)方法,把應(yīng)用程序從處理取得和釋放資源中解放出來。TransactionTemplate是線程安全的。代碼示例如下:

TransactionTemplate tt = new TransactionTemplate(); // 新建一個TransactionTemplate
    Object result = tt.execute(
        new TransactionCallback(){  
            public Object doTransaction(TransactionStatus status){  
                updateOperation();  
                return resultOfUpdateOperation();  
            }  
    }); // 執(zhí)行execute方法進(jìn)行事務(wù)管理

使用TransactionCallback()可以返回一個值。如果使用TransactionCallbackWithoutResult則沒有返回值。

3.2.2 使用PlatformTransactionManager

示例代碼如下:

DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); //定義一個某個框架平臺的TransactionManager,如JDBC、Hibernate
    dataSourceTransactionManager.setDataSource(this.getJdbcTemplate().getDataSource()); // 設(shè)置數(shù)據(jù)源
    DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); // 定義事務(wù)屬性
    transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED); // 設(shè)置傳播行為屬性
    TransactionStatus status = dataSourceTransactionManager.getTransaction(transDef); // 獲得事務(wù)狀態(tài)
    try {
        // 數(shù)據(jù)庫操作
        dataSourceTransactionManager.commit(status);// 提交
    } catch (Exception e) {
        dataSourceTransactionManager.rollback(status);// 回滾
    }

4、聲明式事務(wù)

4.1 配置方式

根據(jù)代理機(jī)制的不同,總結(jié)了五種Spring事務(wù)的配置方式,配置文件如下:
第一種方式:每個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>  

    <!-- 定義事務(wù)管理器(聲明式的事務(wù)) -->  
    <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">  
           <!-- 配置事務(wù)管理器 -->  
           <property name="transactionManager" ref="transactionManager" />     
        <property name="target" ref="userDaoTarget" />  
         <property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao" />
        <!-- 配置事務(wù)屬性 -->  
        <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>  

    <!-- 定義事務(wù)管理器(聲明式的事務(wù)) -->  
    <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">  
        <!-- 配置事務(wù)管理器 -->  
        <property name="transactionManager" ref="transactionManager" />  
        <!-- 配置事務(wù)屬性 -->  
        <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>  

    <!-- 定義事務(wù)管理器(聲明式的事務(wù)) -->  
    <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" />  
        <!-- 配置事務(wù)屬性 -->  
        <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標(biāo)簽配置的攔截器

<?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>  

    <!-- 定義事務(wù)管理器(聲明式的事務(wù)) -->  
    <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>  

    <!-- 定義事務(wù)管理器(聲明式的事務(wù)) -->  
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
</beans>

此時在DAO上需加上@Transactional注解,如下:

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();
    }
   ....
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容