JOTM(Java Open Transaction Manager)鏄疧bjectWeb鐨勪竴涓紑婧怞TA瀹炵幇錛屾湰韜篃鏄紑婧愬簲鐢ㄧ▼搴忔湇鍔″櫒JOnAS(Java Open Application Server)鐨勪竴閮ㄥ垎錛屼負鍏舵彁渚汮TA鍒嗗竷寮忎簨鍔$殑鍔熻兘銆係pring瀵笿OTM鎻愪緵浜嗚緝濂界殑鏀寔錛屾彁渚涗簡涓涓猳rg.springframework.transaction.jta.JotmFactoryBean鐨勬敮鎸佺被錛屽湪Spring2.0涓篃鍖呭惈浜咼OTM鐩稿叧鐨勪竴浜沴ibrary銆?
jotm鐨勪笅杞藉湴鍧涓篽ttp://jotm.objectweb.org,鏈鏂扮増鏈負2.0.10.
涓嬭澆瀹屾垚鍚庤В鍘嬬緝錛岀劧鍚庢墦寮jotm涓嬮潰conf鏂囦歡澶癸紝鎷瘋礉carol.properties鏂囦歡鍒癱lasspath涓紝騫朵慨鏀硅繖涓枃浠跺涓?
carol.properties
- #聽do聽not聽use聽CAROL聽JNDI聽wrapper聽聽聽 聽聽
- carol.start.jndi=false聽聽聽 聽聽
- 聽聽聽 聽聽
- #聽do聽not聽start聽a聽name聽server聽聽聽 聽聽
- carol.start.ns=false聽聽聽 聽聽
- 聽聽聽 聽聽
- #聽Naming聽Factory 聽聽
- carol.jndi.java.naming.factory.url.pkgs=org.apache.naming聽聽
# do not use CAROL JNDI wrapper
carol.start.jndi=false
# do not start a name server
carol.start.ns=false
# Naming Factory
carol.jndi.java.naming.factory.url.pkgs=org.apache.naming
涓婇潰閰嶇疆鏂囦歡鐨勭洰鐨勬槸涓嶄嬌鐢↗NDI鐨勬柟寮忔潵鍔犺澆JOTM鐨勯厤緗紝褰撶劧涔熷彲浠ユ牴鎹渶瑕侀夋嫨鍏跺畠鐨勪竴浜涢厤緗紝渚嬪JTOM鎵鎻愪緵鐨勯粯璁ら厤緗?
鐒跺悗寮濮嬪湪Spring涓婁笅鏂囦腑閰嶇疆JOTM錛屽湪classpath涓緩绔嬩竴涓狝pplicationContext-jotm.xml錛岄厤緗涓?
ApplicationContext-jotm.xml
- <?xml聽version="1.0"聽encoding="UTF-8"?> 聽聽
- <beans聽xmlns="http://www.springframework.org/schema/beans"聽聽
- 聽聽聽聽xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"聽聽
- 聽聽聽聽xsi:schemaLocation="http://www.springframework.org/schema/beans聽http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> 聽聽
- 聽聽
- 聽聽聽聽<bean聽id="jotm"聽class="org.springframework.transaction.jta.JotmFactoryBean"/> 聽聽
- 聽聽聽聽 聽聽
- 聽聽聽聽<bean聽id="txManager"聽class="org.springframework.transaction.jta.JtaTransactionManager"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="userTransaction"聽ref="jotm"聽/> 聽聽
- 聽聽聽聽</bean> 聽聽
- 聽聽
- 聽聽聽聽<bean聽id="ds1"聽class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"聽destroy-method="shutdown"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="dataSource"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽<bean聽class="org.enhydra.jdbc.standard.StandardXADataSource"聽destroy-method="shutdown"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="transactionManager"聽ref="jotm"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="driverName"聽value="com.mysql.jdbc.Driver"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="url"聽value="jdbc:MySQL://localhost:3306/test"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽</bean> 聽聽
- 聽聽聽聽聽聽聽聽</property> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="user"聽value="root"聽/> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="password"聽value="admin"聽/> 聽聽
- 聽聽聽聽</bean> 聽聽
- 聽聽聽聽 聽聽
- 聽聽聽聽<bean聽id="ds2"聽class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"聽destroy-method="shutdown"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="dataSource"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽<bean聽class="org.enhydra.jdbc.standard.StandardXADataSource"聽destroy-method="shutdown"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="transactionManager"聽ref="jotm"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="driverName"聽value="com.mysql.jdbc.Driver"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="url"聽value="jdbc:MySQL://localhost:3306/test2"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽</bean> 聽聽
- 聽聽聽聽聽聽聽聽</property> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="user"聽value="root"聽/> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="password"聽value="admin"聽/> 聽聽
- 聽聽聽聽</bean> 聽聽
- 聽聽
- 聽聽聽聽<bean聽id="template1"聽class="org.springframework.jdbc.core.JdbcTemplate"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="dataSource"聽ref="ds1"聽/> 聽聽
- 聽聽聽聽</bean> 聽聽
- 聽聽聽聽 聽聽
- 聽聽聽聽<bean聽id="template2"聽class="org.springframework.jdbc.core.JdbcTemplate"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="dataSource"聽ref="ds2"聽/> 聽聽
- 聽聽聽聽</bean> 聽聽
- 聽聽聽聽 聽聽
- 聽聽聽聽<bean聽id="dao1"聽class="com.xa.dao.UserDao1"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="jdbcTemplate"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽<ref聽bean="template1"></ref> 聽聽
- 聽聽聽聽聽聽聽聽</property> 聽聽
- 聽聽聽聽</bean> 聽聽
- 聽聽聽聽 聽聽
- 聽聽聽聽<bean聽id="dao2"聽class="com.xa.dao.UserDao2"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="jdbcTemplate"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽<ref聽bean="template2"></ref> 聽聽
- 聽聽聽聽聽聽聽聽</property> 聽聽
- 聽聽聽聽</bean> 聽聽
- 聽聽聽聽 聽聽
- 聽聽聽聽<bean聽id="userServiceTarget"聽class="com.xa.service.UserServiceImpl"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="dao1"聽ref="dao1"/> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="dao2"聽ref="dao2"/> 聽聽
- 聽聽聽聽</bean> 聽聽
- 聽聽
- 聽聽
- 聽聽聽聽<bean聽id="userTest"聽class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">聽聽聽聽 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="transactionManager"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽<ref聽bean="txManager"/> 聽聽
- 聽聽聽聽聽聽聽聽</property>聽聽聽聽 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="target"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽<ref聽bean="userServiceTarget"/> 聽聽
- 聽聽聽聽聽聽聽聽</property> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="transactionAttributes">聽聽聽聽聽聽聽聽 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽<props> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<prop聽key="insert*">PROPAGATION_REQUIRED,-Exception</prop>聽聽聽聽聽聽聽聽聽聽聽聽 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽</props> 聽聽
- 聽聽聽聽聽聽聽聽</property> 聽聽
- 聽聽聽聽</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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="jotm" />
</bean>
<bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
<property name="dataSource">
<bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager" ref="jotm" />
<property name="driverName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:MySQL://localhost:3306/test" />
</bean>
</property>
<property name="user" value="root" />
<property name="password" value="admin" />
</bean>
<bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
<property name="dataSource">
<bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager" ref="jotm" />
<property name="driverName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:MySQL://localhost:3306/test2" />
</bean>
</property>
<property name="user" value="root" />
<property name="password" value="admin" />
</bean>
<bean id="template1" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds1" />
</bean>
<bean id="template2" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="ds2" />
</bean>
<bean id="dao1" class="com.xa.dao.UserDao1">
<property name="jdbcTemplate">
<ref bean="template1"></ref>
</property>
</bean>
<bean id="dao2" class="com.xa.dao.UserDao2">
<property name="jdbcTemplate">
<ref bean="template2"></ref>
</property>
</bean>
<bean id="userServiceTarget" class="com.xa.service.UserServiceImpl">
<property name="dao1" ref="dao1"/>
<property name="dao2" ref="dao2"/>
</bean>
<bean id="userTest" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="txManager"/>
</property>
<property name="target">
<ref bean="userServiceTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>
</props>
</property>
</bean>
</beans>
涓婇潰鏄竴涓畬鏁寸殑Spring涓婁笅鏂囬厤緗紝鍙互鐪嬬涓涓猙ean 鈥渏otm鈥濓紝瀹為檯涓婂紩鐢ㄤ簡Spring鍐呴儴鎵鎻愪緵鐨勫JOTM鏀寔鐨勫伐鍘傜被錛屽弬鑰冧笅闈㈢殑閰嶇疆浠g爜孌?
- <bean聽id="jotm"聽class="org.springframework.transaction.jta.JotmFactoryBean"/>聽聽
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
闅忓悗錛岄厤緗簡JTA浜嬪姟綆$悊鍣紝騫朵笖鍦ㄧ鐞嗗櫒涓嬌鐢ㄤ笂闈㈡墍閰嶇疆鐨刯otm錛屽涓嬮潰鐨勪唬鐮?
- <bean聽id="txManager"聽class="org.springframework.transaction.jta.JtaTransactionManager"> 聽聽
- 聽聽聽聽<property聽name="userTransaction"聽ref="jotm"聽/> 聽聽
- </bean>聽聽
<bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="jotm" />
</bean>
鍐嶆帴涓嬫潵灝辨槸閰嶇疆澶氫釜鏁版嵁婧愪簡錛屼嬌鐢╦otm鎻愪緵鐨刼rg.enhydra.jdbc.pool.StandardXAPoolDataSource綾伙紝鏍規嵁綾誨悕鍙互鏄庣‘鍦扮湅鍑哄畠鏄敤浠ラ厤緗涓暟鎹簮鐨勫暒,閰嶇疆鐨勪唬鐮佸涓?
- <bean聽id="ds1"聽class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"聽destroy-method="shutdown"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="dataSource"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽<bean聽class="org.enhydra.jdbc.standard.StandardXADataSource"聽destroy-method="shutdown"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="transactionManager"聽ref="jotm"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="driverName"聽value="com.mysql.jdbc.Driver"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="url"聽value="jdbc:MySQL://localhost:3306/test"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽</bean> 聽聽
- 聽聽聽聽聽聽聽聽</property> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="user"聽value="root"聽/> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="password"聽value="admin"聽/> 聽聽
- 聽聽聽聽</bean> 聽聽
- 聽聽聽聽 聽聽
- 聽聽聽聽<bean聽id="ds2"聽class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"聽destroy-method="shutdown"> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="dataSource"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽<bean聽class="org.enhydra.jdbc.standard.StandardXADataSource"聽destroy-method="shutdown"> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="transactionManager"聽ref="jotm"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="driverName"聽value="com.mysql.jdbc.Driver"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽聽<property聽name="url"聽value="jdbc:MySQL://localhost:3306/test2"聽/> 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽</bean> 聽聽
- 聽聽聽聽聽聽聽聽</property> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="user"聽value="root"聽/> 聽聽
- 聽聽聽聽聽聽聽聽<property聽name="password"聽value="admin"聽/> 聽聽
- 聽聽聽聽</bean>聽聽
<bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
<property name="dataSource">
<bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager" ref="jotm" />
<property name="driverName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:MySQL://localhost:3306/test" />
</bean>
</property>
<property name="user" value="root" />
<property name="password" value="admin" />
</bean>
<bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
<property name="dataSource">
<bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
<property name="transactionManager" ref="jotm" />
<property name="driverName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:MySQL://localhost:3306/test2" />
</bean>
</property>
<property name="user" value="root" />
<property name="password" value="admin" />
</bean>
榪欓噷閰嶇疆鐨勪袱涓暟鎹簮閮借繛鎺ュ埌鏈湴鐨刴ysql錛屽疄闄呬笂鍙互榪炴帴鍒頒笉鍚岀殑db server鍜屼笉鍚岀被鍨嬬殑鏁版嵁搴擄紝宸茬粡緇忚繃嫻嬭瘯錛岃繖閲屼負浜嗘柟渚匡紝鍦ㄦ湰鍦板緩绔嬩簡涓や釜涓嶅悓鐨勬暟鎹簱(test,test2)鍋氭祴璇曘?
闅忓悗鐨勯厤緗熀鏈笂鍜屾櫘閫氱殑Spring涓婁笅鏂囬厤緗浉鍚屼簡錛屾牴鎹笉鍚岀殑鏁版嵁婧愰厤緗袱涓猨dbcTemplate錛屼袱涓猟ao鍒嗗埆寮曠敤涓嶅悓鐨刯dbcTemplate, 灝嗕袱涓猟ao娉ㄥ叆鍒癠serService涓? 鏈鍚庡皢service綰沖叆浜嬪姟綆$悊,騫跺湪浜嬪姟浠g悊閰嶇疆涓厤緗洖婊氳鍒?鎰忔濅負濡傞亣寮傚父錛屽垯寮哄埗鍥炴粴鍐呭銆傞厤緗涓嬫墍紺?
- <property聽name="transactionAttributes">聽聽聽聽聽聽聽聽 聽聽
- 聽聽聽聽<props> 聽聽
- 聽聽聽聽聽聽聽聽<prop聽key="insert*">PROPAGATION_REQUIRED,-Exception</prop>聽聽聽聽聽聽聽聽聽聽聽聽 聽聽
- 聽聽聽聽</props> 聽聽
- </property>聽聽
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>
</props>
</property>
榪欐牱錛屼竴涓嬌鐢↗OTM JTA浜嬪姟鐨勭畝鍗曞簲鐢ㄧ畻澶ц嚧鎴愬瀷浜嗭紝鏈鍚庯紝鍐欎竴涓狫Unit錛屾潵嫻嬭瘯涓涓嬬粨鏋?
TestXa.java
- package聽com.xa; 聽聽
- 聽聽
- import聽org.springframework.context.ApplicationContext; 聽聽
- import聽org.springframework.test.AbstractDependencyInjectionSpringContextTests; 聽聽
- 聽聽
- import聽com.xa.service.UserService; 聽聽
- 聽聽
- public聽class聽TestXa聽extends聽AbstractDependencyInjectionSpringContextTests 聽聽
- { 聽聽
- 聽聽聽聽protected聽String[]聽getConfigLocations()聽{ 聽聽
- 聽聽聽聽聽聽聽聽return聽new聽String[]聽{聽"classpath:ApplicationContext-jotm.xml"聽}; 聽聽
- 聽聽聽聽} 聽聽
- 聽聽
- 聽聽聽聽public聽void聽testInsertBothDatabase()聽{ 聽聽
- 聽聽聽聽聽聽聽聽ApplicationContext聽ctx聽=聽this.getApplicationContext(); 聽聽
- 聽聽聽聽聽聽聽聽UserService聽ut聽=聽(UserService)ctx.getBean("userTest"); 聽聽
- 聽聽聽聽聽聽聽聽try聽{ 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽ut.insertBothDatabase("1",聽null); 聽聽
- 聽聽聽聽聽聽聽聽} 聽聽
- 聽聽聽聽聽聽聽聽catch聽(Exception聽e)聽{ 聽聽
- 聽聽聽聽聽聽聽聽聽聽聽聽e.printStackTrace(); 聽聽
- 聽聽聽聽聽聽聽聽} 聽聽
- 聽聽聽聽} 聽聽
- }聽聽
package com.xa;
import org.springframework.context.ApplicationContext;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import com.xa.service.UserService;
public class TestXa extends AbstractDependencyInjectionSpringContextTests
{
protected String[] getConfigLocations() {
return new String[] { "classpath:ApplicationContext-jotm.xml" };
}
public void testInsertBothDatabase() {
ApplicationContext ctx = this.getApplicationContext();
UserService ut = (UserService)ctx.getBean("userTest");
try {
ut.insertBothDatabase("1", null);
}
catch (Exception e) {
e.printStackTrace();
}
}
}
鍦╰est涓紝璋冪敤浜哢serService鐨刬nsertBothDatabase鏂規硶錛屾湁涓や釜鍙傛暟錛寀serId鍜孶serName錛屽彟澶栧湪鏂規硶鐨勫疄鐜頒腑璋冪敤浜嗕袱涓嬌鐢ㄤ笉鍚屾暟鎹簮dao錛屽垎鍒悜涓や釜涓嶅悓鐨勬暟鎹簱鎻掑叆杈撳叆錛岃宼est2鏁版嵁搴撶殑xa_test琛ㄤ腑錛宯ame瀛楁鏄笉鍏佽涓虹┖鐨勶紝鍥犳錛屽湪鎻掑叆test2鏁版嵁搴撴椂浼氬け璐?
榪愯榪欎釜test錛岀劧鍚庡療鐪嬫暟鎹簱緇撴灉錛氾級錛宼est鍜宼est2鏁版嵁搴撲腑閮芥病鏈夋彃鍏ユ垚鍔燂紝鐪媠erviceImpl涓殑浠g爜鍙互鐭ラ亾錛岄昏緫涓奷ao1浼氬厛浜巇ao2鎵ц錛屼絾鏄敱浜嶫TA浜嬪姟錛屽湪dao2鎻掑叆鏁版嵁鍑虹幇寮傚父鏃舵暣涓簨鍔¤鍥炴粴錛岀敱浜庝簨鍔¤閰嶇疆鍦╯ervice灞傦紝dao1鍜宒ao2閮借綰沖叆涓涓簨鍔¤繘琛岀鐞嗭紝鍛靛懙銆備慨鏀逛竴涓嬫柟娉曠殑鍙傛暟錛屼慨鏀逛負
- ut.insertBothDatabase("1",聽"name1");聽聽
ut.insertBothDatabase("1", "name1");
鐒跺悗鍐嶈瘯璇晅est鐪嬫暟鎹簱緇撴灉錛屽浣曪紵

]]>