<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    eric-1001c

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      3 隨筆 :: 45 文章 :: 12 評論 :: 0 Trackbacks

    Spring事務傳播機制解惑

    概述

    當我們調用一個基于Spring的Service接口方法(如UserService#addUser())時,它將運行于Spring管理的事務環境中,Service接口方法可能會在內部調用其它的Service接口方法以共同完成一個完整的業務操作,因此就會產生服務接口方法嵌套調用的情況,Spring通過事務傳播行為控制當前的事務如何傳播到被嵌套調用的目標服務接口方法中。

    事務傳播是Spring進行事務管理的重要概念,其重要性怎么強調都不為過。但是事務傳播行為也是被誤解最多的地方,在本文里,我們將詳細分析不同事務傳播行為的表現形式,掌握它們之間的區別。

    事務傳播行為種類

    Spring在TransactionDefinition接口中規定了7種類型的事務傳播行為,它們規定了事務方法和事務方法發生嵌套調用時事務如何進行傳播:

    1事務傳播行為類型

    事務傳播行為類型

    說明

    PROPAGATION_REQUIRED

    如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。這是最常見的選擇。

    PROPAGATION_SUPPORTS

    支持當前事務,如果當前沒有事務,就以非事務方式執行。

    PROPAGATION_MANDATORY

    使用當前的事務,如果當前沒有事務,就拋出異常。

    PROPAGATION_REQUIRES_NEW

    新建事務,如果當前存在事務,把當前事務掛起。

    PROPAGATION_NOT_SUPPORTED

    以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

    PROPAGATION_NEVER

    以非事務方式執行,如果當前存在事務,則拋出異常。

    PROPAGATION_NESTED

    如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

    當使用PROPAGATION_NESTED時,底層的數據源必須基于JDBC 3.0,并且實現者需要支持保存點事務機制。

    幾種容易引起誤解的組合事務傳播行為

    當服務接口方法分別使用表1中不同的事務傳播行為,且這些接口方法又發生相互調用的情況下,大部分組合都是一目了然,容易理解的。但是,也存在一些容易引起誤解的組合事務傳播方式。

    下面,我們通過兩個具體的服務接口的組合調用行為來破解這一難點。這兩個服務接口分別是UserService和ForumService,UserSerice有一個addCredits()方法,ForumSerivce#addTopic()方法調用了UserSerice#addCredits()方法,發生關聯性服務方法的調用:

    public class ForumService {

    private UserService userService;

    public void addTopic(){①調用其它服務接口的方法

    //add Topic…

    userService.addCredits();②被關聯調用的業務方法

    }

    }

    嵌套調用的事務方法

    對Spring事務傳播行為最常見的一個誤解是:當服務接口方法發生嵌套調用時,被調用的服務方法只能聲明為PROPAGATION_NESTED。這種觀點犯了望文生義的錯誤,誤認為PROPAGATION_NESTED是專為方法嵌套準備的。這種誤解遺害不淺,執有這種誤解的開發者錯誤地認為:應盡量不讓Service類的業務方法發生相互的調用,Service類只能調用DAO層的DAO類,以避免產生嵌套事務。

    其實,這種顧慮是完全沒有必要的,PROPAGATION_REQUIRED已經清楚地告訴我們:事務的方法會足夠“聰明”地判斷上下文是否已經存在一個事務中,如果已經存在,就加入到這個事務中,否則創建一個新的事務。

    依照上面的例子,假設我們將ForumService#addTopic()和UserSerice#addCredits()方法的事務傳播行為都設置為PROPAGATION_REQUIRED,這兩個方法將運行于同一個事務中。

    為了清楚地說明這點,可以將Log4J的日志設置為DEBUG級別,以觀察Spring事務管理器內部的運行情況。下面將兩個業務方法都設置為PROPAGATION_REQUIRED,Spring所輸出的日志信息如下:

    Using transaction object

    [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@e3849c]

    ①為ForumService#addTopic()新建一個事務

    Creating new transaction with name [com.baobaotao.service.ForumService.addTopic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

    Acquired Connection [org.apache.commons.dbcp.PoolableConnection@dc41c5] for JDBC transaction

    Switching JDBC Connection [org.apache.commons.dbcp.PoolableConnection@dc41c5] to manual commit

    Bound value [org.springframework.jdbc.datasource.ConnectionHolder@ee1ede] for key [org.apache.commons.dbcp.BasicDataSource@4204] to thread [main]

    Initializing transaction synchronization

    Getting transaction for [com.baobaotao.service.ForumService.addTopic]

    Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@ee1ede] for key [org.apache.commons.dbcp.BasicDataSource@4204] bound to thread [main]

    Using transaction object [org.springframework.jdbc.datasource.DataSourceTransactionManager$DataSourceTransactionObject@8b8a47]

    UserService#addCredits()簡單地加入到已存在的事務中(即①處創建的事務)

    Participating in existing transaction

    Getting transaction for [com.baobaotao.service.UserService.addCredits]

    Completing transaction for [com.baobaotao.service.UserService.addCredits]

    Completing transaction for [com.baobaotao.service.ForumService.addTopic]

    Triggering beforeCommit synchronization

    Triggering beforeCompletion synchronization

    Initiating transaction commit

    ③調用底層Connection#commit()方法提交事務

    Committing JDBC transaction on Connection [org.apache.commons.dbcp.PoolableConnection@dc41c5]

    Triggering afterCommit synchronization

    Triggering afterCompletion synchronization

    Clearing transaction synchronization

    嵌套事務

    將ForumService#addTopic()設置為PROPAGATION_REQUIRED時,UserSerice#addCredits()設置為PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS、PROPAGATION_MANDATORY時,運行的效果都是一致的(當然,如果單獨調用addCredits()就另當別論了)。

    當addTopic()運行在一個事務下(如設置為PROPAGATION_REQUIRED),而addCredits()設置為PROPAGATION_NESTED時,如果底層數據源支持保存點,Spring將為內部的addCredits()方法產生的一個內嵌的事務。如果addCredits()對應的內嵌事務執行失敗,事務將回滾到addCredits()方法執行前的點,并不會將整個事務回滾。內嵌事務是內層事務的一部分,所以只有外層事務提交時,嵌套事務才能一并提交。

    嵌套事務不能夠提交,它必須通過外層事務來完成提交的動作,外層事務的回滾也會造成內部事務的回滾。

    嵌套事務和新事務

    PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED也是容易混淆的兩個傳播行為。PROPAGATION_REQUIRES_NEW 啟動一個新的、和外層事務無關的“內部”事務。該事務擁有自己的獨立隔離級別和鎖,不依賴于外部事務,獨立地提交和回滾。當內部事務開始執行時,外部事務將被掛起,內務事務結束時,外部事務才繼續執行。

    由此可見, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大區別在于:PROPAGATION_REQUIRES_NEW 將創建一個全新的事務,它和外層事務沒有任何關系,而 PROPAGATION_NESTED 將創建一個依賴于外層事務的子事務,當外層事務提交或回滾時,子事務也會連帶提交和回滾。

    其它需要注意問題

    以下幾個問題值得注意:

    1) 當業務方法被設置為PROPAGATION_MANDATORY時,它就不能被非事務的業務方法調用。如將ForumService#addTopic()設置為PROPAGATION_MANDATORY,如果展現層的Action直接調用addTopic()方法,將引發一個異常。正確的情況是:addTopic()方法必須被另一個帶事務的業務方法調用(如ForumService#otherMethod())。所以PROPAGATION_MANDATORY的方法一般都是被其它業務方法間接調用的。

    2) 當業務方法被設置為PROPAGATION_NEVER時,它將不能被擁有事務的其它業務方法調用。假設UserService#addCredits()設置為PROPAGATION_NEVER,當ForumService# addTopic()擁有一個事務時,addCredits()方法將拋出異常。所以PROPAGATION_NEVER方法一般是被直接調用的。

    3)當方法被設置為PROPAGATION_NOT_SUPPORTED時,外層業務方法的事務會被掛起,當內部方法運行完成后,外層方法的事務重新運行。如果外層方法沒有事務,直接運行,不需要做任何其它的事。

    小結

    在Spring聲明式事務管理的配置中,事務傳播行為是最容易被誤解的配置項,原因在于事務傳播行為名稱(如PROPAGATION_NESTED:嵌套式事務)和代碼結構的類似性上(業務類方法嵌套調用另一個業務類方法)。這種誤解在很多Spring開發者中廣泛存在,本文深入講解了Spring事務傳播行為對業務方法嵌套調用的真實影響,希望能幫助讀者化解對事務傳播行為的困惑。

    posted on 2008-04-05 12:45 Eric-1001c 閱讀(404) 評論(0)  編輯  收藏 所屬分類: Hibernate
    主站蜘蛛池模板: 成人免费视频试看120秒| 久久久国产精品福利免费| 丁香花免费完整高清观看| 亚洲精品高清久久| 日本亚洲欧洲免费天堂午夜看片女人员 | 亚洲中文字幕久久精品无码VA| 一级毛片在线观看免费| 亚洲影院在线观看| 999久久久免费精品播放| 亚洲色偷偷av男人的天堂| 51在线视频免费观看视频| 亚洲成年人免费网站| 国产成人yy免费视频| 亚洲日韩中文字幕一区| 国产精品免费看久久久无码| 免费一级毛片在线播放放视频| 亚洲性在线看高清h片| 国产色爽免费无码视频| 亚洲韩国—中文字幕| 免费国产作爱视频网站| 亚洲αⅴ无码乱码在线观看性色| 免费一级毛片不卡不收费| 一个人看的www视频免费在线观看| 亚洲色中文字幕无码AV| 91大神免费观看| 亚洲国产成人AV在线播放 | 99免费观看视频| 亚洲不卡影院午夜在线观看| 国产伦精品一区二区三区免费迷| 一个人看的hd免费视频| 久久精品国产亚洲AV嫖农村妇女 | 波多野结衣一区二区免费视频| 一个人看的免费观看日本视频www 一个人看的免费视频www在线高清动漫 | 国产一区二区三区亚洲综合| 国产亚洲情侣一区二区无| 99在线观看免费视频| 亚洲爆乳AAA无码专区| 国产亚洲精品无码成人| 久久久久久免费视频| 好湿好大好紧好爽免费视频| 亚洲白嫩在线观看|