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

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

參考文章:

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

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

Spring事務(wù)管理及幾種簡單的實現(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ù)具體運行狀態(tài)

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

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

Spring本身并不支持事務(wù)實現(xiàn)嗜历,只是負責包裝底層事務(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進行持久化數(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進行持久化數(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進行持久化時使用

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ù)這個返回值進行優(yōu)化鞍恢,確保事務(wù)是只讀的
} 

2.3 TransactionStatus運行狀態(tài)

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

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

3、編程式事務(wù)

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

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

3.2 如何實現(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方法進行事務(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ù)代理機制的不同,總結(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標簽配置的攔截器

<?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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市仅仆,隨后出現(xiàn)的幾起案子器赞,更是在濱河造成了極大的恐慌,老刑警劉巖墓拜,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夹姥,死亡現(xiàn)場離奇詭異榛鼎,居然都是意外死亡萝喘,警方通過查閱死者的電腦和手機匙隔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涌韩,“玉大人畔柔,你說我怎么就攤上這事∶潮玻” “怎么了释树?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵肠槽,是天一觀的道長擎淤。 經(jīng)常有香客問我奢啥,道長,這世上最難降的妖魔是什么嘴拢? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任桩盲,我火速辦了婚禮,結(jié)果婚禮上席吴,老公的妹妹穿的比我還像新娘赌结。我一直安慰自己,他們只是感情好孝冒,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布柬姚。 她就那樣靜靜地躺著,像睡著了一般庄涡。 火紅的嫁衣襯著肌膚如雪量承。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天穴店,我揣著相機與錄音撕捍,去河邊找鬼。 笑死泣洞,一個胖子當著我的面吹牛忧风,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播球凰,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狮腿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了呕诉?” 一聲冷哼從身側(cè)響起缘厢,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎义钉,沒想到半個月后昧绣,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡捶闸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年夜畴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片删壮。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡贪绘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出央碟,到底是詐尸還是另有隱情税灌,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站菱涤,受9級特大地震影響苞也,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜粘秆,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一如迟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧攻走,春花似錦殷勘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至摘符,卻和暖如春贤斜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背议慰。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工蠢古, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人别凹。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓草讶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親炉菲。 傳聞我的和親對象是個殘疾皇子堕战,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容