摘要
Spring框架是一個流行的基于輕量級控ò 46;反轉容器的Java/J2EE應用框架,尤其在數& #25454;訪問和事務管理方面的能力是眾? 2;周知的。Spring的聲明性事務分離可以ò 12;用到任何POJO目標對象,并且包含所? 7;EJB基于容器管理事務中的已聲明事務 。后臺的事務管理器支持簡單的基é 10;JDBC的事務和全功能的基于JTA的J2EE事務。 ;
這篇文章詳細的討論了Spring的事務管? 02;特性。重點是如何在使用JTA作為后臺 ;事務策略的基礎上讓POJO利用Spring的聲明&# 24615;事務,這也顯示了Spring的事務服務可& #20197;無縫地與J2EE服務器(如BEA WebLogic Server的事務協調器)的事務協調器進行 ;交互,作為EJB CMT傳統事務分離方式的一個替代者。
POJO的聲明性事務
作為Spring聲明性事務分離方式的樣例? 92;讓我們來看一下Spring的樣例應用PetClinic的 0013;心服務外觀中的配置:
清單1:
他遵循Spring的標準XMLBean定義格式。定義? 2;:
1、一個DataSource引用,指向一個JNDI位置—? 12;J2EE服務器管理下這將從JNDI環境中獲取&# 29305;定的DataSource。
2、一個應用服務實現—這是一個POJO, ;封裝了業務和數據訪問邏輯。在這% 324;實現了應用中的Clinic服務接口。
3、一個應用服務的事務代理—這個 0195;理為目標服務定義了事務屬性,匹 配特定的方法名模式并為之創建相ò 12;的事務。在實際的事務管理中,代&# 29702;指向一個PlatformTransactionManager實現。
注意 :除了顯式的代理定義A 292;Spring還支持自動代理機制和通過Commons Attributes或J2SE 5.0注解實現源程序級的元數據使用。&# 36825;些可選方法的討論超過了本文的范 ;圍。可以參考Spring的文檔來了解相關? 4;節。
業務接口和業務實現是特定于應用 0340;并且不需要關心Spring或者Spring的事務管 702;。普通Java對象可以作為服務的目標? 45;象,而且任何普通Java接口可以作為? 1;務的接口。下面是一個Clinic接口的示? 63;:
清單2:
這個接口的實現如下顯示,假設他 0351;用JDBC來執行必要的數據訪問。他通$ 807;bean屬性的設置方法來獲取JDBC的DataSource;這? 2;上面的配置中的dataSource屬性定義相對應& #12290;
清單3:
如你所見,代碼相當直接。我們使 9992;一個簡單的Java對象,而事務管理由 107;務代理來處理,這個我們會在下面& #35752;論。
注意在PetClinic示例應用中實際的基于JDBC? 0;Clinic實現利用了Spring的JDBC支持類來避免直 5509;使用JDBC的API。雖然Spring的事務管理也可 0197;與普通的基于JDBC實現一起工作,就 521;上面的示例。
定義事務代理
除了JdbcClinic實例以外,配置中也定義了& #19968;個事務代理。如果愿意這個代理? 2;暴露的實際接口也可以顯式定義。 0664;認情況下,所有由目標對象實現的 接口都暴露出來,在這個例子中就? 59;應用的Clinic服務接口。
從客戶端的觀點來看,"clinic" bean只是這個應用的Clinic接口的實現。客 5143;端不需要知道這會被一個事務代理 所處理。這就是接口的能力:一個? 52;接的目標對象的引用可以容易的被&# 19968;個實現相同接口的代理所代替—在 這兒就是一個隱式創建事務的代理z 90;
代理的具體事務行為會由為根據特 3450;的方法或方法命名模式而定義的事 務屬性來驅動,就像下面的例子所? 34;:
清單3:
Key屬性決定代理將為方法提供什么樣 的事務行為。這個屬性的最重要部? 98;就是事務傳播行為。下面是一些可&# 36873;的屬性值:
1、PROPAGATION_REQUIRED -- 支持當前的事務,如果不存在就創ó 14;一個新的。這是最常用的選擇。
2、PROPAGATION_SUPPORTS -- 支持當前的事務,如果不存在就不? 51;用事務。
3、PROPAGATION_MANDATORY -- 支持當前的事務,如果不存在就拋? 86;異常。
4、PROPAGATION_REQUIRES_NEW -- 創建一個新的事務,并暫停當前的é 07;務(如果存在)。
5、PROPAGATION_NOT_SUPPORTED -- 不使用事務,并暫停當前的事務(? 14;果存在)。
6、PROPAGATION_NEVER -- 不使用事務,如果當前存在事務就ü 43;出異常。
7、PROPAGATION_NESTED -- 如果當前存在事務就作為嵌入事務? 91;行,否則與PROPAGATION_REQUIRED類似。
前6個事務策略與EJB的CMT類似,而且使 992;相同的常量名,因此對EJB開發人員? 9;說是很親切的。第7個策略PROPAGATION_NESTED是Spring&# 25552;供的一個變體:他需要事務管理器 ;(如DataSourceTransactionManager) 提供類似JDBC3.0那樣的保存點API來嵌套事 1153;行為或者通過
JTA支持嵌套事務。
事務屬性中的readOnly標識指示相應的事 1153;應該作為一個只讀事務來優化。這 是一個優化提示:一些事務策略在? 25;種情況下可以得到很好的性能優化&# 65292;如使用ORM工具如Hibernate或TopLink時避免臟數 454;檢查(“flush”嘗試)。
在事務屬性中還有一個“timeout”選項? 9;定義事務的超時秒數。在JTA中,這個 屬性會簡單地傳遞給J2EE服務器的事務& #21327;調器并被正確地解釋。
使用事務代理
在運行時,客戶端會取得一個“clinic&rdquo ;引用并轉換為Clinic接口,然后調用如loadPe t或storePet方法。這就隱式地使用了Spring的? 7;務代理,通過“事務解釋器”在目? 31;對象中注冊;這樣一個新的事務就&# 21019;建了,然后具體的工作就會代理給 ;JdbcClinic的目標方法。
圖1示例了一個使用“建議鏈”并到$ 798;最后目標的AOP代理的潛在概念。在? 5;個示例中,唯一的建議是一個事務 5299;釋器用來包裝目標方法的事務行為 。這是一種用來在聲明性事務功能? 79;使用的基于代理的AOP。
Figure 1. An AOP proxy with an advisor chain and a target at the end
例如,一個PetClinic應用的WEB層組件可以執 ;行ServletContext定位來獲取Spring WebApplicationContext的引用并且獲取受管理的“clinic&rd quo;BEAN:
清單4:
在調用storePet() 之前,Spring的事務代理隱式地創建一個 ;事務。當storePet() 調用返回時,事務將提交或回滾。? 70;省情況下任何RuntimeException或Error將導致回滾z 90;實際的提交或回滾可以是可以定義&# 30340;:Spring的事務屬性支持“回滾規則” 0340;概念。
例如,我們可以可以引入一個強制 0340;PetClinicException并且告訴事務代理在拋出異? 0;時回滾:
清單5:
這兒也有一個類似的“提交規則”? 21;法,指示特定的異常將觸發一次提&# 20132;。
注意上面示例的顯式定位引用的方 7861;只是一種訪問受Spring管理BEAN的方法的? 4;化,可以用在任何WEB資源如servlet或filter。 2312;構建基于Spring自身的MVC框架時,BEAN可以 0452;接被注射到WEB控制器中。當然也支y 45;在如Struts, WebWork, JSF, and Tapestry框架中訪問Spring管理BEAN。詳情可以參 2771;Spring的文檔。
PlatformTransactionManager策略
Spring事務支持的核心接口是org.springframework.transaction.Platf ormTransactionManager。所有Spring的事務分離功能都會&# 22996;托給PlatformTransactionManager(傳給相應的TransactionDefinition實 例)來做實際的事務執行。雖然PlatformTrans actionManager接口可以直接調用,但通常應用 只需要配置一個具體的事務管理器? 82;且通過聲明性事務來分離事務。
Spring提供幾種不同的PlatformTransactionManager實現,分 0026;如下兩個類別:
1、本地事務策略—支持單一資源的 0107;務(通常是單個數據庫),其包括 org.springframework.jdbc.datasource.DataSourceTransactionManager和 org.springframework.orm.hibernate.HibernateTransactionManager。
2、全局事務管理—支持可能跨越多 0010;資源的全局事務。其相應的類為org.spri ngframework.transaction.jta.JtaTransactionManager,將事務委托給遵循JTA& #35268;范的事務協調器(通常為J2EE服務器&# 65292;但不是強制的)。
PlatformTransactionManager抽象的主要價值在于應用不& #20877;被綁定在特定的事務管理環境。? 6;反,事務策略可以很容易地切換—$ 890;過選擇不同的PlatformTransactionManager實現類。這就 ;使得應用代碼與聲明事務分離保持 968;致,而不需要考慮應用組件所使用& #30340;環境了。
例如,應用的初始版本可能布署在Tom cat上,與單個Oracle數據庫交互。這可以 041;便地利用Spring的事務分離特性,只要 6873;擇基于JDBC的DataSourceTransactionManager作為使用的事務 策略。Spring會分離事務,而JDBC驅動會執 4892;相應的原始JDBC事務。
相同應用的另一個版本可能會布署 2312;WebLogic服務器上,使用兩個Oracle數據庫。&# 24212;用代碼和事務分離不需要改變。唯 ;一不同的是選擇作為JtaTransactionManager事務策略 ;,讓Spring來分離事務而WebLogic服務器的事? 3;協調器來執行事務。
JTA UserTransaction與JTA TransactionManager比較
讓我們來看一下Spring對JTA支持的細節。&# 34429;然并非經常需要考慮這個細節但了 ;解相關的細節還有必要的。對簡單 340;用例如前面章節的示例,標準的JtaTransa ctionManager定義已經足夠了,
缺省的Spring JtaTransactionManager設置會從標準JNDI位置(J2EE規范所 定義的java:comp/UserTransaction)獲取JTA的javax.transaction.UserTransaction對 象。這對大部分標準J2EE環境來說已經& #36275;夠了。
然而,缺省的JtaTransactionManager不能執行事務? 2;停(也就是說不支持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUP PORTED)。原因就在于標準的JTA UserTransaction接口不支持事務的暫停和恢復? 2;而只支持開始和完成新的事務。
為了實現事務的暫停,需要一個javax.trans action.TransactionManager實例,他提供了JTA定義的標準& #30340;暫停和恢復方法。不幸的是,J2EE沒&# 26377;為JTA TransactionManager定義標準的JNDI位置!因此,我們 ;需要使用廠商自己的定位機制。
清單6:
J2EE本質上沒有考慮將JTA TransactionManager接口作為公共API的一部分。JTA規? 39;自身定義了將TransactionManager接口作為容器集 成的想法。雖然這是可以理解的,ê 94;是JTA TransactionManager的標準JNDI位置還是可以增加一定 ;的價值,特別是對輕量級容器如Spring,? 25;樣任何J2EE服務器就可以用統一的方? 5;來定位JTA TransactionManager了。
不僅Spring的JtaTransactionManager可以從訪問中獲益, O/R映射工具如Hibernate, Apache OJB, and Kodo JDO也能得到好處,因為他們需要在JTA環 ;境中執行緩存同步的能力(釋放緩 384;意味著JTA事務的完成)。這種注冊? 7;務同步的能力只有JTA TransactionManager接口才能提供,而UserTransaction是處理 981;了的。因此,這些工具都需要實現& #33258;己的TransactionManager定位器。
為JTA TransactionManager定義標準的JNDI位置是許多底層軟 ;件供應商最期望J2EE實現的功能。如果 J2EE5.0的規范制定團隊能夠認識到這個? 5;性的重要性就太好了。幸運地是, 9640;級J2EE服務器如WebLogic Server已經考慮將JTA TransactionManager作為公共的API包含在擴展功能中 。
在WebLogic JTA中實現Spring的事務分離
在WebLogic Server中,JTA TransactionManager官方的JNDI位置定義為javax.transaction.TransactionManager 2290;這個值可以在Spring的JtaTransactionManager中作為“transa ctionManagerName”使用。原則上這樣就可以在WebLog ic"s JTA系統中實現事務暫停了,也就是說&# 25903;持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUPPORTED行為。
除了標準的JtaTransactionManager和其支持的通用? 7;置選項外,Spring還提供了一個專用的WebLo gicJtaTransactionManager適配器來直接利用WebLogic的JTA擴展&# 12290;
在享受自動探測WebLogic的JTA TransactionManager的便利之外,他提供超越標準JTA 的三個重要特性:
1、事務命名—暴露出Spring的事務名給WebLo gic Server,使得Spring事務在WebLogic的事務監聽器可& #35265;。缺省的,Spring會使用聲明性事務的 完整方法名。
2、每事務隔離級別—將Spring事務屬性è 13;定義的隔離級別應用到WebLogic JTA事務中。這使得每個事務都可以定&# 20041;數據庫的隔離級別,而這是標準JTA 152;不支持的。
3、強制事務恢復—即使在暫停的事 1153;被標識為回滾時也可以恢復。這需 要使用WebLogic的擴展TransactionManager接口來調用forceResume ()方法。
Figure 2. WebLogic Server"s transaction monitor (click the image for a full-size screen shot)
Spring的WebLogicJtaTransactionManager有效地為基于Spring的應用&# 25552;供了WebLogic Server事務管理的全部功能。這使得Spring事& #21153;分離成為一種能與EJB CMT竟爭的產品,而且提供了相同級別&# 30340;事務支持。
Spring and EJB CMT
如上所示,Spring的POJO聲明性事務分離可& #20197;作為一種除傳統EJB CMT這外的選擇。但是Spring與EJB并不是完成& #20114;斥的,Spring的應用上下文也可以作為 EJB fa?ade的后臺來管理數據訪問(DAO)和& #20854;他細紋理的業務對象。
在EJB情景中,事務是由EJB CMT來驅動的。對Spring來說,數據訪問支 345;特性會自動檢測到這樣的環境并且& #37319;用相應的事務。例如,Spring對Hibernate的支 ;持能夠提供隱式的資源管理,即使 159;EJB驅動的事務,甚至可以在不需要? 2;改任何DAO代碼的情況下提供相同的語 義。
Spring有效的解耦了DAO實現與實際的運行&# 29615;境。DAO可以參與Spring的事務就像參與EJB CMT事務一樣。這不僅簡化在其他環境&# 20013;的重用,而且更方便在J2EE容器外進 4892;測試。
結論
Spring框架為J2EE和非J2EE環境提供了全量的é 07;務分離的特性,特別表現在POJO的聲? 6;性事務上。他用一種靈活而非侵入 4335;的方式為非EJB環境中的事務分離提? 79;了便利。與EJB不同,這樣的事務性POJO 4212;用對象可以很容易的被測試和在J2EE 481;器外補重用。
Spring提供了各種事務策略,如JtaTransactionManager是 用來代理J2EE服務器的事務協調器,而J DBC DataSourceTransactionManager是用來為簡單的JDBC DataSource(就是單一目標數據庫)執行事 1153;。Spring可以很容易為不同的環境通過&# 21518;臺配置的簡單修改來調整事務策略 ;。
超越標準的JTA支持,Spring為WebLogic Server的JTA擴展提供了完善的集成,可以 903;持高級特性如事務監視和每事務隔& #31163;級別。通過對WebLogic Server的特殊支持,基于Spring的應用可以完& #20840;利用WebLogic Server的事務管理功能。
Spring事務分離是繼EJB CMT之外的另一種可選方式,特別是對&# 37027;些基于POJO的輕量級架構。在那只是 2240;為選擇LSSB(本地無狀態會話BEAN)來應 用聲明性事務的情況下,基于Spring的POJO 6381;務模型是一種可行的選擇,他提供 了非常高層的靈活性、可測試性和? 25;用性。
資源
JTA - The JTA specification JTA規范
WebLogic JTA - Documentation of WebLogic"s JTA extensions WebLogicJTA擴展文檔
關于作者
Juergen Hoeller是Spring框架的創始人之一
Spring框架是一個流行的基于輕量級控ò 46;反轉容器的Java/J2EE應用框架,尤其在數& #25454;訪問和事務管理方面的能力是眾? 2;周知的。Spring的聲明性事務分離可以ò 12;用到任何POJO目標對象,并且包含所? 7;EJB基于容器管理事務中的已聲明事務 。后臺的事務管理器支持簡單的基é 10;JDBC的事務和全功能的基于JTA的J2EE事務。 ;
這篇文章詳細的討論了Spring的事務管? 02;特性。重點是如何在使用JTA作為后臺 ;事務策略的基礎上讓POJO利用Spring的聲明&# 24615;事務,這也顯示了Spring的事務服務可& #20197;無縫地與J2EE服務器(如BEA WebLogic Server的事務協調器)的事務協調器進行 ;交互,作為EJB CMT傳統事務分離方式的一個替代者。
POJO的聲明性事務
作為Spring聲明性事務分離方式的樣例? 92;讓我們來看一下Spring的樣例應用PetClinic的 0013;心服務外觀中的配置:
清單1:
<bean id="dataSource"><br> class="org.springframework.jndi.JndiObjectFactoryBean"><br><br><br><property name="jndiName"><br><value>java:comp/env/jdbc/petclinic</value><br></property><br></bean>
<bean id="transactionManager"><br> class="org.springframework.transaction.jta.JtaTransactionManager"/><br><br><bean id="clinicTarget"><br> class="org.springframework.samples.petclinic.jdbc.JdbcClinic"><br><property name="dataSource"><ref bean="dataSource"></ref><br></property><br><br><bean id="clinic"><br> class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><br><property name="transactionManager"><ref bean="transactionManager"></ref><br><property name="target"><ref bean="clinicTarget"></ref><br><property name="transactionAttributes"><br><props><br><prop key="load*">PROPAGATION_REQUIRED,readOnly</prop><br><prop key="store*">PROPAGATION_REQUIRED</prop><br></props><br></property><br></property></property></bean></bean></bean>
他遵循Spring的標準XMLBean定義格式。定義? 2;:
1、一個DataSource引用,指向一個JNDI位置—? 12;J2EE服務器管理下這將從JNDI環境中獲取&# 29305;定的DataSource。
2、一個應用服務實現—這是一個POJO, ;封裝了業務和數據訪問邏輯。在這% 324;實現了應用中的Clinic服務接口。
3、一個應用服務的事務代理—這個 0195;理為目標服務定義了事務屬性,匹 配特定的方法名模式并為之創建相ò 12;的事務。在實際的事務管理中,代&# 29702;指向一個PlatformTransactionManager實現。
注意 :除了顯式的代理定義A 292;Spring還支持自動代理機制和通過Commons Attributes或J2SE 5.0注解實現源程序級的元數據使用。&# 36825;些可選方法的討論超過了本文的范 ;圍。可以參考Spring的文檔來了解相關? 4;節。
業務接口和業務實現是特定于應用 0340;并且不需要關心Spring或者Spring的事務管 702;。普通Java對象可以作為服務的目標? 45;象,而且任何普通Java接口可以作為? 1;務的接口。下面是一個Clinic接口的示? 63;:
清單2:
public interface Clinic {
Pet loadPet(int id);
void storePet(Pet pet);
...
}
這個接口的實現如下顯示,假設他 0351;用JDBC來執行必要的數據訪問。他通$ 807;bean屬性的設置方法來獲取JDBC的DataSource;這? 2;上面的配置中的dataSource屬性定義相對應& #12290;
清單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) {
...
}
}
...
}
如你所見,代碼相當直接。我們使 9992;一個簡單的Java對象,而事務管理由 107;務代理來處理,這個我們會在下面& #35752;論。
注意在PetClinic示例應用中實際的基于JDBC? 0;Clinic實現利用了Spring的JDBC支持類來避免直 5509;使用JDBC的API。雖然Spring的事務管理也可 0197;與普通的基于JDBC實現一起工作,就 521;上面的示例。
定義事務代理
除了JdbcClinic實例以外,配置中也定義了& #19968;個事務代理。如果愿意這個代理? 2;暴露的實際接口也可以顯式定義。 0664;認情況下,所有由目標對象實現的 接口都暴露出來,在這個例子中就? 59;應用的Clinic服務接口。
從客戶端的觀點來看,"clinic" bean只是這個應用的Clinic接口的實現。客 5143;端不需要知道這會被一個事務代理 所處理。這就是接口的能力:一個? 52;接的目標對象的引用可以容易的被&# 19968;個實現相同接口的代理所代替—在 這兒就是一個隱式創建事務的代理z 90;
代理的具體事務行為會由為根據特 3450;的方法或方法命名模式而定義的事 務屬性來驅動,就像下面的例子所? 34;:
清單3:
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="store*">PROPAGATION_REQUIRED</prop>
Key屬性決定代理將為方法提供什么樣 的事務行為。這個屬性的最重要部? 98;就是事務傳播行為。下面是一些可&# 36873;的屬性值:
1、PROPAGATION_REQUIRED -- 支持當前的事務,如果不存在就創ó 14;一個新的。這是最常用的選擇。
2、PROPAGATION_SUPPORTS -- 支持當前的事務,如果不存在就不? 51;用事務。
3、PROPAGATION_MANDATORY -- 支持當前的事務,如果不存在就拋? 86;異常。
4、PROPAGATION_REQUIRES_NEW -- 創建一個新的事務,并暫停當前的é 07;務(如果存在)。
5、PROPAGATION_NOT_SUPPORTED -- 不使用事務,并暫停當前的事務(? 14;果存在)。
6、PROPAGATION_NEVER -- 不使用事務,如果當前存在事務就ü 43;出異常。
7、PROPAGATION_NESTED -- 如果當前存在事務就作為嵌入事務? 91;行,否則與PROPAGATION_REQUIRED類似。
前6個事務策略與EJB的CMT類似,而且使 992;相同的常量名,因此對EJB開發人員? 9;說是很親切的。第7個策略PROPAGATION_NESTED是Spring&# 25552;供的一個變體:他需要事務管理器 ;(如DataSourceTransactionManager) 提供類似JDBC3.0那樣的保存點API來嵌套事 1153;行為或者通過
JTA支持嵌套事務。
事務屬性中的readOnly標識指示相應的事 1153;應該作為一個只讀事務來優化。這 是一個優化提示:一些事務策略在? 25;種情況下可以得到很好的性能優化&# 65292;如使用ORM工具如Hibernate或TopLink時避免臟數 454;檢查(“flush”嘗試)。
在事務屬性中還有一個“timeout”選項? 9;定義事務的超時秒數。在JTA中,這個 屬性會簡單地傳遞給J2EE服務器的事務& #21327;調器并被正確地解釋。
使用事務代理
在運行時,客戶端會取得一個“clinic&rdquo ;引用并轉換為Clinic接口,然后調用如loadPe t或storePet方法。這就隱式地使用了Spring的? 7;務代理,通過“事務解釋器”在目? 31;對象中注冊;這樣一個新的事務就&# 21019;建了,然后具體的工作就會代理給 ;JdbcClinic的目標方法。
圖1示例了一個使用“建議鏈”并到$ 798;最后目標的AOP代理的潛在概念。在? 5;個示例中,唯一的建議是一個事務 5299;釋器用來包裝目標方法的事務行為 。這是一種用來在聲明性事務功能? 79;使用的基于代理的AOP。
Figure 1. An AOP proxy with an advisor chain and a target at the end
例如,一個PetClinic應用的WEB層組件可以執 ;行ServletContext定位來獲取Spring WebApplicationContext的引用并且獲取受管理的“clinic&rd quo;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的事務代理隱式地創建一個 ;事務。當storePet() 調用返回時,事務將提交或回滾。? 70;省情況下任何RuntimeException或Error將導致回滾z 90;實際的提交或回滾可以是可以定義&# 30340;:Spring的事務屬性支持“回滾規則” 0340;概念。
例如,我們可以可以引入一個強制 0340;PetClinicException并且告訴事務代理在拋出異? 0;時回滾:
清單5:
<prop key="load*">PROPAGATION_REQUIRED,readOnly,-PetClinicException</prop>
<prop key="store*">PROPAGATION_REQUIRED,-PetClinicException</prop>
這兒也有一個類似的“提交規則”? 21;法,指示特定的異常將觸發一次提&# 20132;。
注意上面示例的顯式定位引用的方 7861;只是一種訪問受Spring管理BEAN的方法的? 4;化,可以用在任何WEB資源如servlet或filter。 2312;構建基于Spring自身的MVC框架時,BEAN可以 0452;接被注射到WEB控制器中。當然也支y 45;在如Struts, WebWork, JSF, and Tapestry框架中訪問Spring管理BEAN。詳情可以參 2771;Spring的文檔。
PlatformTransactionManager策略
Spring事務支持的核心接口是org.springframework.transaction.Platf ormTransactionManager。所有Spring的事務分離功能都會&# 22996;托給PlatformTransactionManager(傳給相應的TransactionDefinition實 例)來做實際的事務執行。雖然PlatformTrans actionManager接口可以直接調用,但通常應用 只需要配置一個具體的事務管理器? 82;且通過聲明性事務來分離事務。
Spring提供幾種不同的PlatformTransactionManager實現,分 0026;如下兩個類別:
1、本地事務策略—支持單一資源的 0107;務(通常是單個數據庫),其包括 org.springframework.jdbc.datasource.DataSourceTransactionManager和 org.springframework.orm.hibernate.HibernateTransactionManager。
2、全局事務管理—支持可能跨越多 0010;資源的全局事務。其相應的類為org.spri ngframework.transaction.jta.JtaTransactionManager,將事務委托給遵循JTA& #35268;范的事務協調器(通常為J2EE服務器&# 65292;但不是強制的)。
PlatformTransactionManager抽象的主要價值在于應用不& #20877;被綁定在特定的事務管理環境。? 6;反,事務策略可以很容易地切換—$ 890;過選擇不同的PlatformTransactionManager實現類。這就 ;使得應用代碼與聲明事務分離保持 968;致,而不需要考慮應用組件所使用& #30340;環境了。
例如,應用的初始版本可能布署在Tom cat上,與單個Oracle數據庫交互。這可以 041;便地利用Spring的事務分離特性,只要 6873;擇基于JDBC的DataSourceTransactionManager作為使用的事務 策略。Spring會分離事務,而JDBC驅動會執 4892;相應的原始JDBC事務。
相同應用的另一個版本可能會布署 2312;WebLogic服務器上,使用兩個Oracle數據庫。&# 24212;用代碼和事務分離不需要改變。唯 ;一不同的是選擇作為JtaTransactionManager事務策略 ;,讓Spring來分離事務而WebLogic服務器的事? 3;協調器來執行事務。
JTA UserTransaction與JTA TransactionManager比較
讓我們來看一下Spring對JTA支持的細節。&# 34429;然并非經常需要考慮這個細節但了 ;解相關的細節還有必要的。對簡單 340;用例如前面章節的示例,標準的JtaTransa ctionManager定義已經足夠了,
缺省的Spring JtaTransactionManager設置會從標準JNDI位置(J2EE規范所 定義的java:comp/UserTransaction)獲取JTA的javax.transaction.UserTransaction對 象。這對大部分標準J2EE環境來說已經& #36275;夠了。
然而,缺省的JtaTransactionManager不能執行事務? 2;停(也就是說不支持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUP PORTED)。原因就在于標準的JTA UserTransaction接口不支持事務的暫停和恢復? 2;而只支持開始和完成新的事務。
為了實現事務的暫停,需要一個javax.trans action.TransactionManager實例,他提供了JTA定義的標準& #30340;暫停和恢復方法。不幸的是,J2EE沒&# 26377;為JTA TransactionManager定義標準的JNDI位置!因此,我們 ;需要使用廠商自己的定位機制。
清單6:
<bean id="transactionManager"><br> class="org.springframework.transaction.jta.JtaTransactionManager"><br><br><br><property name="transactionManagerName"><br><value>vendorSpecificJndiLocation</value><br></property><br></bean>
J2EE本質上沒有考慮將JTA TransactionManager接口作為公共API的一部分。JTA規? 39;自身定義了將TransactionManager接口作為容器集 成的想法。雖然這是可以理解的,ê 94;是JTA TransactionManager的標準JNDI位置還是可以增加一定 ;的價值,特別是對輕量級容器如Spring,? 25;樣任何J2EE服務器就可以用統一的方? 5;來定位JTA TransactionManager了。
不僅Spring的JtaTransactionManager可以從訪問中獲益, O/R映射工具如Hibernate, Apache OJB, and Kodo JDO也能得到好處,因為他們需要在JTA環 ;境中執行緩存同步的能力(釋放緩 384;意味著JTA事務的完成)。這種注冊? 7;務同步的能力只有JTA TransactionManager接口才能提供,而UserTransaction是處理 981;了的。因此,這些工具都需要實現& #33258;己的TransactionManager定位器。
為JTA TransactionManager定義標準的JNDI位置是許多底層軟 ;件供應商最期望J2EE實現的功能。如果 J2EE5.0的規范制定團隊能夠認識到這個? 5;性的重要性就太好了。幸運地是, 9640;級J2EE服務器如WebLogic Server已經考慮將JTA TransactionManager作為公共的API包含在擴展功能中 。
在WebLogic JTA中實現Spring的事務分離
在WebLogic Server中,JTA TransactionManager官方的JNDI位置定義為javax.transaction.TransactionManager 2290;這個值可以在Spring的JtaTransactionManager中作為“transa ctionManagerName”使用。原則上這樣就可以在WebLog ic"s JTA系統中實現事務暫停了,也就是說&# 25903;持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUPPORTED行為。
除了標準的JtaTransactionManager和其支持的通用? 7;置選項外,Spring還提供了一個專用的WebLo gicJtaTransactionManager適配器來直接利用WebLogic的JTA擴展&# 12290;
在享受自動探測WebLogic的JTA TransactionManager的便利之外,他提供超越標準JTA 的三個重要特性:
1、事務命名—暴露出Spring的事務名給WebLo gic Server,使得Spring事務在WebLogic的事務監聽器可& #35265;。缺省的,Spring會使用聲明性事務的 完整方法名。
2、每事務隔離級別—將Spring事務屬性è 13;定義的隔離級別應用到WebLogic JTA事務中。這使得每個事務都可以定&# 20041;數據庫的隔離級別,而這是標準JTA 152;不支持的。
3、強制事務恢復—即使在暫停的事 1153;被標識為回滾時也可以恢復。這需 要使用WebLogic的擴展TransactionManager接口來調用forceResume ()方法。
Figure 2. WebLogic Server"s transaction monitor (click the image for a full-size screen shot)
Spring的WebLogicJtaTransactionManager有效地為基于Spring的應用&# 25552;供了WebLogic Server事務管理的全部功能。這使得Spring事& #21153;分離成為一種能與EJB CMT竟爭的產品,而且提供了相同級別&# 30340;事務支持。
Spring and EJB CMT
如上所示,Spring的POJO聲明性事務分離可& #20197;作為一種除傳統EJB CMT這外的選擇。但是Spring與EJB并不是完成& #20114;斥的,Spring的應用上下文也可以作為 EJB fa?ade的后臺來管理數據訪問(DAO)和& #20854;他細紋理的業務對象。
在EJB情景中,事務是由EJB CMT來驅動的。對Spring來說,數據訪問支 345;特性會自動檢測到這樣的環境并且& #37319;用相應的事務。例如,Spring對Hibernate的支 ;持能夠提供隱式的資源管理,即使 159;EJB驅動的事務,甚至可以在不需要? 2;改任何DAO代碼的情況下提供相同的語 義。
Spring有效的解耦了DAO實現與實際的運行&# 29615;境。DAO可以參與Spring的事務就像參與EJB CMT事務一樣。這不僅簡化在其他環境&# 20013;的重用,而且更方便在J2EE容器外進 4892;測試。
結論
Spring框架為J2EE和非J2EE環境提供了全量的é 07;務分離的特性,特別表現在POJO的聲? 6;性事務上。他用一種靈活而非侵入 4335;的方式為非EJB環境中的事務分離提? 79;了便利。與EJB不同,這樣的事務性POJO 4212;用對象可以很容易的被測試和在J2EE 481;器外補重用。
Spring提供了各種事務策略,如JtaTransactionManager是 用來代理J2EE服務器的事務協調器,而J DBC DataSourceTransactionManager是用來為簡單的JDBC DataSource(就是單一目標數據庫)執行事 1153;。Spring可以很容易為不同的環境通過&# 21518;臺配置的簡單修改來調整事務策略 ;。
超越標準的JTA支持,Spring為WebLogic Server的JTA擴展提供了完善的集成,可以 903;持高級特性如事務監視和每事務隔& #31163;級別。通過對WebLogic Server的特殊支持,基于Spring的應用可以完& #20840;利用WebLogic Server的事務管理功能。
Spring事務分離是繼EJB CMT之外的另一種可選方式,特別是對&# 37027;些基于POJO的輕量級架構。在那只是 2240;為選擇LSSB(本地無狀態會話BEAN)來應 用聲明性事務的情況下,基于Spring的POJO 6381;務模型是一種可行的選擇,他提供 了非常高層的靈活性、可測試性和? 25;用性。
資源
JTA - The JTA specification JTA規范
WebLogic JTA - Documentation of WebLogic"s JTA extensions WebLogicJTA擴展文檔
關于作者
Juergen Hoeller是Spring框架的創始人之一
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
