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

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

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

    Java Votary

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      48 隨筆 :: 1 文章 :: 80 評論 :: 0 Trackbacks
    在SPRING中實現(xiàn)事務暫停

    作者:Juergen Hoeller

    譯者:xMatrix





    版權聲明:任何獲得Matrix授權的網站,轉載時請務必以超鏈接形式標明文章原始出處和作者信息及本聲明
    作者:Juergen Hoeller;xMatrix
    原文地址:http://dev2dev.bea.com/pub/a/2005/07/spring_transactions.html
    中文地址:http://www.matrix.org.cn/resource/article/44/44054_Transaction+Spring.html
    關鍵詞: Transaction Suspension Spring

    摘要

    Spring 框架是一個流行的基于輕量級控制反轉容器的Java/J2EE應用框架,尤其在數(shù)據訪問和事務管理方面的能力是眾所周知的。Spring的聲明性事務分離 可以應用到任何POJO目標對象,并且包含所有EJB基于容器管理事務中的已聲明事務。后臺的事務管理器支持簡單的基于JDBC的事務和全功能的基于 JTA的J2EE事務。

    這篇文章詳細的討論了Spring的事務管理特性。重點是如何在使用JTA作為后臺事務策略的基礎上讓POJO利 用Spring的聲明性事務,這也顯示了Spring的事務服務可以無縫地與J2EE服務器(如BEA WebLogic Server的事務協(xié)調器)的事務協(xié)調器進行交互,作為EJB CMT傳統(tǒng)事務分離方式的一個替代者。

    POJO的聲明性事務

    作為Spring聲明性事務分離方式的樣例,讓我們來看一下Spring的樣例應用PetClinic的中心服務外觀中的配置:
    清單1:
    <bean id="dataSource" 
       class="org.springframework.jndi.JndiObjectFactoryBean">
         <property name="jndiName">
            <value>java:comp/env/jdbc/petclinic</value>
         </property>
    </bean>

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

    <bean id="clinicTarget"
       class="org.springframework.samples.petclinic.jdbc.JdbcClinic">
        <property name="dataSource"><ref bean="dataSource"/></property>
    </bean>

    <bean id="clinic"
       class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager"><ref bean="transactionManager"/></property>
        <property name="target"><ref bean="clinicTarget"/></property>
        <property name="transactionAttributes">
            <props>
                <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="store*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>


    他遵循Spring的標準XMLBean定義格式。定義了:
    1、一個DataSource引用,指向一個JNDI位置—在J2EE服務器管理下這將從JNDI環(huán)境中獲取特定的DataSource。
    2、一個應用服務實現(xiàn)—這是一個POJO,封裝了業(yè)務和數(shù)據訪問邏輯。在這里實現(xiàn)了應用中的Clinic服務接口。
    3、一個應用服務的事務代理—這個代理為目標服務定義了事務屬性,匹配特定的方法名模式并為之創(chuàng)建相應的事務。在實際的事務管理中,代理指向一個PlatformTransactionManager實現(xiàn)。
    注意:除了顯式的代理定義,Spring還支持自動代理機制和通過Commons Attributes或J2SE 5.0注解實現(xiàn)源程序級的元數(shù)據使用。這些可選方法的討論超過了本文的范圍。可以參考Spring的文檔來了解相關細節(jié)。


    業(yè)務接口和業(yè)務實現(xiàn)是特定于應用的并且不需要關心Spring或者Spring的事務管理。普通Java對象可以作為服務的目標對象,而且任何普通Java接口可以作為服務的接口。下面是一個Clinic接口的示例:
    清單2:
    public interface Clinic {
        Pet loadPet(int id);
        void storePet(Pet pet);
        ...
    }



    這個接口的實現(xiàn)如下顯示,假設他使用JDBC來執(zhí)行必要的數(shù)據訪問。他通過bean屬性的設置方法來獲取JDBC的DataSource;這與上面的配置中的dataSource屬性定義相對應。
    清單3:
    public class JdbcClinic implements Clinic {

        private DataSource dataSource;

        public void setDataSource(DataSource dataSource) {
          this.dataSource = dataSource;
        }

        public Pet loadPet(int id) {
          try {
              Connection con = this.dataSource.getConnection();
              ...
          }
          catch (SQLException ex) {
            ...
          }
        }

        public void storePet(Pet pet) {
          try {
              Connection con = this.dataSource.getConnection();
              ...
          }
          catch (SQLException ex) {
            ...
          }
        }

        ...
    }



    如你所見,代碼相當直接。我們使用一個簡單的Java對象,而事務管理由事務代理來處理,這個我們會在下面討論。
    注意在PetClinic示例應用中實際的基于JDBC的Clinic實現(xiàn)利用了Spring的JDBC支持類來避免直接使用JDBC的API。雖然Spring的事務管理也可以與普通的基于JDBC實現(xiàn)一起工作,就向上面的示例。

    定義事務代理
    除了JdbcClinic實例以外,配置中也定義了一個事務代理。如果愿意這個代理所暴露的實際接口也可以顯式定義。默認情況下,所有由目標對象實現(xiàn)的接口都暴露出來,在這個例子中就是應用的Clinic服務接口。

    從客戶端的觀點來看,"clinic" bean只是這個應用的Clinic接口的實現(xiàn)。客戶端不需要知道這會被一個事務代理所處理。這就是接口的能力:一個直接的目標對象的引用可以容易的被一個實現(xiàn)相同接口的代理所代替—在這兒就是一個隱式創(chuàng)建事務的代理。
    代理的具體事務行為會由為根據特定的方法或方法命名模式而定義的事務屬性來驅動,就像下面的例子所示:
    清單3:
    <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
    <prop key="store*">PROPAGATION_REQUIRED</prop>


    Key屬性決定代理將為方法提供什么樣的事務行為。這個屬性的最重要部分就是事務傳播行為。下面是一些可選的屬性值:
    1、PROPAGATION_REQUIRED --支持當前的事務,如果不存在就創(chuàng)建一個新的。這是最常用的選擇。
    2、PROPAGATION_SUPPORTS --支持當前的事務,如果不存在就不使用事務。
    3、PROPAGATION_MANDATORY --支持當前的事務,如果不存在就拋出異常。
    4、PROPAGATION_REQUIRES_NEW --創(chuàng)建一個新的事務,并暫停當前的事務(如果存在)。
    5、PROPAGATION_NOT_SUPPORTED --不使用事務,并暫停當前的事務(如果存在)。
    6、PROPAGATION_NEVER --不使用事務,如果當前存在事務就拋出異常。
    7、PROPAGATION_NESTED --如果當前存在事務就作為嵌入事務執(zhí)行,否則與PROPAGATION_REQUIRED類似。

    前6 個事務策略與EJB的CMT類似,而且使用相同的常量名,因此對EJB開發(fā)人員來說是很親切的。第7個策略PROPAGATION_NESTED是 Spring提供的一個變體:他需要事務管理器(如DataSourceTransactionManager)提供類似JDBC3.0那樣的保存點 API來嵌套事務行為或者通過
    JTA支持嵌套事務。

    事務屬性中的readOnly標識指示相應的事務應該作為一個只讀事務來優(yōu)化。這是一個優(yōu)化提示:一些事務策略在這種情況下可以得到很好的性能優(yōu)化,如使用ORM工具如Hibernate或TopLink時避免臟數(shù)據檢查(“flush”嘗試)。

    在事務屬性中還有一個“timeout”選項來定義事務的超時秒數(shù)。在JTA中,這個屬性會簡單地傳遞給J2EE服務器的事務協(xié)調器并被正確地解釋。

    使用事務代理
    在 運行時,客戶端會取得一個“clinic”引用并轉換為Clinic接口,然后調用如loadPet或storePet方法。這就隱式地使用了 Spring的事務代理,通過“事務解釋器”在目標對象中注冊;這樣一個新的事務就創(chuàng)建了,然后具體的工作就會代理給JdbcClinic的目標方法。
    圖1示例了一個使用“建議鏈”并到達最后目標的AOP代理的潛在概念。在這個示例中,唯一的建議是一個事務解釋器用來包裝目標方法的事務行為。這是一種用來在聲明性事務功能下使用的基于代理的AOP。



    Figure 1. An AOP proxy with an advisor chain and a target at the end

    例如,一個PetClinic應用的WEB層組件可以執(zhí)行ServletContext定位來獲取Spring WebApplicationContext的引用并且獲取受管理的“clinic”BEAN:
    清單4:
    WebApplicationContext ctx = 
       WebApplicationContexUtils.getWebApplicationContext(servletContext);
    Clinic clinic = (Clinic) ctx.getBean("clinic);

    Pet pet = new Pet();
    pet.setName("my new cat");

    clinic.storePet(pet);


    在 調用storePet()之前,Spring的事務代理隱式地創(chuàng)建一個事務。當storePet()調用返回時,事務將提交或回滾。缺省情況下任何 RuntimeException或Error將導致回滾。實際的提交或回滾可以是可以定義的:Spring的事務屬性支持“回滾規(guī)則”的概念。

    例如,我們可以可以引入一個強制的PetClinicException并且告訴事務代理在拋出異常時回滾:
    清單5:
    <prop key="load*">PROPAGATION_REQUIRED,readOnly,-PetClinicException</prop>
    <prop key="store*">PROPAGATION_REQUIRED,-PetClinicException</prop>


    這兒也有一個類似的“提交規(guī)則”語法,指示特定的異常將觸發(fā)一次提交。
    注 意上面示例的顯式定位引用的方法只是一種訪問受Spring管理BEAN的方法的變化,可以用在任何WEB資源如servlet或filter。在構建基 于Spring自身的MVC框架時,BEAN可以直接被注射到WEB控制器中。當然也支持在如Struts, WebWork, JSF, and Tapestry框架中訪問Spring管理BEAN。詳情可以參考Spring的文檔。

    PlatformTransactionManager策略

    Spring 事務支持的核心接口是org.springframework.transaction.PlatformTransactionManager。所有 Spring的事務分離功能都會委托給PlatformTransactionManager(傳給相應的TransactionDefinition實 例)來做實際的事務執(zhí)行。雖然PlatformTransactionManager接口可以直接調用,但通常應用只需要配置一個具體的事務管理器并且通 過聲明性事務來分離事務。

    Spring提供幾種不同的PlatformTransactionManager實現(xiàn),分為如下兩個類別:
    1、 本地事務策略—支持單一資源的事務(通常是單個數(shù)據庫),其包括 org.springframework.jdbc.datasource.DataSourceTransactionManager和 org.springframework.orm.hibernate.HibernateTransactionManager。
    2、全局事務管理—支持可能跨越多個資源的全局事務。其相應的類為org.springframework.transaction.jta.JtaTransactionManager,將事務委托給遵循JTA規(guī)范的事務協(xié)調器(通常為J2EE服務器,但不是強制的)。

    PlatformTransactionManager 抽象的主要價值在于應用不再被綁定在特定的事務管理環(huán)境。相反,事務策略可以很容易地切換—通過選擇不同的 PlatformTransactionManager實現(xiàn)類。這就使得應用代碼與聲明事務分離保持一致,而不需要考慮應用組件所使用的環(huán)境了。

    例 如,應用的初始版本可能布署在Tomcat上,與單個Oracle數(shù)據庫交互。這可以方便地利用Spring的事務分離特性,只要選擇基于JDBC的 DataSourceTransactionManager作為使用的事務策略。Spring會分離事務,而JDBC驅動會執(zhí)行相應的原始JDBC事務。

    相 同應用的另一個版本可能會布署在WebLogic服務器上,使用兩個Oracle數(shù)據庫。應用代碼和事務分離不需要改變。唯一不同的是選擇作為 JtaTransactionManager事務策略,讓Spring來分離事務而WebLogic服務器的事務協(xié)調器來執(zhí)行事務。

    JTA UserTransaction與JTA TransactionManager比較
    讓我們來看一下Spring對JTA支持的細節(jié)。雖然并非經常需要考慮這個細節(jié)但了解相關的細節(jié)還有必要的。對簡單的用例如前面章節(jié)的示例,標準的JtaTransactionManager定義已經足夠了,
    缺 省的Spring JtaTransactionManager設置會從標準JNDI位置(J2EE規(guī)范所定義的java:comp/UserTransaction)獲取 JTA的javax.transaction.UserTransaction對象。這對大部分標準J2EE環(huán)境來說已經足夠了。

    然而, 缺省的JtaTransactionManager不能執(zhí)行事務暫停(也就是說不支持PROPAGATION_REQUIRES_NEW和 PROPAGATION_NOT_SUPPORTED)。原因就在于標準的JTA UserTransaction接口不支持事務的暫停和恢復,而只支持開始和完成新的事務。

    為了實現(xiàn)事務的暫停,需要一個 javax.transaction.TransactionManager實例,他提供了JTA定義的標準的暫停和恢復方法。不幸的是,J2EE沒有為 JTA TransactionManager定義標準的JNDI位置!因此,我們需要使用廠商自己的定位機制。
    清單6:
    <bean id="transactionManager" 
       class="org.springframework.transaction.jta.JtaTransactionManager">
         <property name="transactionManagerName">
            <value>vendorSpecificJndiLocation</value>
         </property>
    </bean>



    J2EE 本質上沒有考慮將JTA TransactionManager接口作為公共API的一部分。JTA規(guī)范自身定義了將TransactionManager接口作為容器集成的想 法。雖然這是可以理解的,但是JTA TransactionManager的標準JNDI位置還是可以增加一定的價值,特別是對輕量級容器如Spring,這樣任何J2EE服務器就可以用統(tǒng) 一的方式來定位JTA TransactionManager了。

    不僅Spring的JtaTransactionManager可以從 訪問中獲益,O/R映射工具如Hibernate, Apache OJB, and Kodo JDO也能得到好處,因為他們需要在JTA環(huán)境中執(zhí)行緩存同步的能力(釋放緩存意味著JTA事務的完成)。這種注冊事務同步的能力只有JTA TransactionManager接口才能提供,而UserTransaction是處理不了的。因此,這些工具都需要實現(xiàn)自己的 TransactionManager定位器。

    為JTA TransactionManager定義標準的JNDI位置是許多底層軟件供應商最期望J2EE實現(xiàn)的功能。如果J2EE5.0的規(guī)范制定團隊能夠認識 到這個特性的重要性就太好了。幸運地是,高級J2EE服務器如WebLogic Server已經考慮將JTA TransactionManager作為公共的API包含在擴展功能中。

    在WebLogic JTA中實現(xiàn)Spring的事務分離
    在WebLogic Server中,JTA TransactionManager官方的JNDI位置定義為javax.transaction.TransactionManager。這個值可以 在Spring的JtaTransactionManager中作為“transactionManagerName”使用。原則上這樣就可以在 WebLogic's JTA系統(tǒng)中實現(xiàn)事務暫停了,也就是說支持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUPPORTED行 為。

    除了標準的JtaTransactionManager和其支持的通用配置選項外,Spring還提供了一個專用的WebLogicJtaTransactionManager適配器來直接利用WebLogic的JTA擴展。

    在享受自動探測WebLogic的JTA TransactionManager的便利之外,他提供超越標準JTA的三個重要特性:
    1、事務命名—暴露出Spring的事務名給WebLogic Server,使得Spring事務在WebLogic的事務監(jiān)聽器可見。缺省的,Spring會使用聲明性事務的完整方法名。
    2、每事務隔離級別—將Spring事務屬性中定義的隔離級別應用到WebLogic JTA事務中。這使得每個事務都可以定義數(shù)據庫的隔離級別,而這是標準JTA所不支持的。
    3、強制事務恢復—即使在暫停的事務被標識為回滾時也可以恢復。這需要使用WebLogic的擴展TransactionManager接口來調用forceResume()方法。

    image
    Figure 2. WebLogic Server's transaction monitor (click the image for a full-size screen shot)

    Spring的WebLogicJtaTransactionManager有效地為基于Spring的應用提供了WebLogic Server事務管理的全部功能。這使得Spring事務分離成為一種能與EJB CMT竟爭的產品,而且提供了相同級別的事務支持。

    Spring and EJB CMT

    如 上所示,Spring的POJO聲明性事務分離可以作為一種除傳統(tǒng)EJB CMT這外的選擇。但是Spring與EJB并不是完成互斥的,Spring的應用上下文也可以作為EJB fa&ccedil;ade的后臺來管理數(shù)據訪問(DAO)和其他細紋理的業(yè)務對象。

    在EJB情景中,事務是由EJB CMT來驅動的。對Spring來說,數(shù)據訪問支持特性會自動檢測到這樣的環(huán)境并且采用相應的事務。例如,Spring對Hibernate的支持能夠提 供隱式的資源管理,即使是EJB驅動的事務,甚至可以在不需要修改任何DAO代碼的情況下提供相同的語義。
    Spring有效的解耦了DAO實現(xiàn)與實際的運行環(huán)境。DAO可以參與Spring的事務就像參與EJB CMT事務一樣。這不僅簡化在其他環(huán)境中的重用,而且更方便在J2EE容器外進行測試。

    結論
    Spring框架為J2EE和非J2EE環(huán)境提供了全量的事務分離的特性,特別表現(xiàn)在POJO的聲明性事務上。他用一種靈活而非侵入式的方式為非EJB環(huán)境中的事務分離提供了便利。與EJB不同,這樣的事務性POJO應用對象可以很容易的被測試和在J2EE容器外補重用。

    Spring 提供了各種事務策略,如JtaTransactionManager是用來代理J2EE服務器的事務協(xié)調器,而JDBC DataSourceTransactionManager是用來為簡單的JDBC DataSource(就是單一目標數(shù)據庫)執(zhí)行事務。Spring可以很容易為不同的環(huán)境通過后臺配置的簡單修改來調整事務策略。

    超越 標準的JTA支持,Spring為WebLogic Server的JTA擴展提供了完善的集成,可以支持高級特性如事務監(jiān)視和每事務隔離級別。通過對WebLogic Server的特殊支持,基于Spring的應用可以完全利用WebLogic Server的事務管理功能。

    Spring事務分離是繼 EJB CMT之外的另一種可選方式,特別是對那些基于POJO的輕量級架構。在那只是因為選擇LSSB(本地無狀態(tài)會話BEAN)來應用聲明性事務的情況下,基 于Spring的POJO服務模型是一種可行的選擇,他提供了非常高層的靈活性、可測試性和重用性。

    資源
    &#8226;JTA - The JTA specification JTA規(guī)范
    &#8226;WebLogic JTA - Documentation of WebLogic's JTA extensions WebLogic  JTA擴展文檔

    關于作者
    Juergen Hoeller是Spring框架的創(chuàng)始人之一
    posted on 2005-12-16 22:39 Dion 閱讀(5069) 評論(1)  編輯  收藏 所屬分類: Springframework

    評論

    # re: 在SPRING中實現(xiàn)事務暫停[未登錄] 2008-03-02 23:58 spring
    好啊,,,,頂  回復  更多評論
      

    主站蜘蛛池模板: 国产精品成人免费福利| 国产免费区在线观看十分钟| 国产成人精品无码免费看 | 亚洲欧洲日韩国产| 在线观看免费无码视频| 亚洲综合伊人久久大杳蕉| 日韩视频在线免费观看| 亚洲AV一二三区成人影片| 在线视频免费观看高清| 亚洲黄色一级毛片| 久久国产免费福利永久| 亚洲人成在线免费观看| 最新中文字幕免费视频| 亚洲人成未满十八禁网站| 日本a级片免费看| 九九久久精品国产免费看小说| a级特黄毛片免费观看| 国产成人无码综合亚洲日韩| 国产一精品一av一免费爽爽| 精品国产精品久久一区免费式| 亚洲一区二区三区国产精品| 中文字幕无码毛片免费看| 久久久亚洲欧洲日产国码二区 | 色屁屁www影院免费观看视频| 久久精品一本到99热免费| 免费福利在线播放| 亚洲夂夂婷婷色拍WW47| 国产高清在线免费视频| 久久一区二区三区免费| 亚洲夜夜欢A∨一区二区三区| 最新亚洲精品国偷自产在线| 亚洲av无码乱码在线观看野外| 亚洲另类自拍丝袜第1页| 日本xxwwxxww在线视频免费| 一级毛片正片免费视频手机看| 国产成人免费午夜在线观看| 最新亚洲人成网站在线观看| 亚洲香蕉网久久综合影视| 国产一卡2卡3卡4卡无卡免费视频 国产一卡二卡3卡四卡免费 | 无码国产精品一区二区免费16 | 亚洲精华液一二三产区|