假如业务中要用到多个数据库,我们希望在业务方法中,当对某一个数据库的数据表进行操作的事务失败并回退(rollback),另外某一个数据库的数据表的操作事务也要回退,但应用一般的事务管理达不到这样的事务管理效果,这就需要实现 JTA 事务管理了。
这里我们在SPring中集成 Object web 的一个开源JTA实现JOTM (可以在http://jotm.objectweb.org下载完整版) 来实现JTA事务管理。
1、将必须的类包放入类路径中:
jotm.jar, xapool.jar, jotm_jrmp_stubs.jar, jta-spect1_0_1.jar, connector-1_5.jar等等。
2、编写JOTM配置文件carol.properties,将其放到类路径下:
Java代码
#JNDI调用协议
carol.protocols=jrmp
#不使用CAROL JNDI封装器
carol.start.jndi=false
#不启动命名服务器
carol.start.ns=false
spring为JOTM提供了一个org.springframework.transaction.jta.JotmFactoryBean 支持类,可以用其方便地创建本地JOTM实例。
<?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:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="mysqldatasource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"> <property name="dataSource"><!--内部XA数据源 --><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/mdg" /> </bean> </property> <property name="user" value="root" /> <property name="password" value="8324759" /> </bean> <bean id="h2datasource" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"> <property name="dataSource"><!--内部XA数据源 --><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="8324759" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!--<property name="configLocation" value="classpath:hibernate.cfg.xml"> </property> --><property name="dataSource" ref="mysqldatasource"> </property> <property name="mappingResources"> <list> <value>com/ky/ssh/model/Admin.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.jdbc.batch_size">50</prop> <prop key="hibernate.cache.use_query_cache">true</prop> <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> </props> </property> <property name="jtaTransactionManager"> <ref bean="jotm" /> </property> </bean> <bean id="sessionFactory2" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <!--<property name="configLocation" value="classpath:hibernate3.cfg.xml"> </property> --><property name="dataSource" ref="h2datasource"> </property> <property name="mappingResources"> <list> <value>com/ky/ssh/database/User.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MYSQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.jdbc.batch_size">50</prop> <prop key="hibernate.cache.use_query_cache">true</prop> <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> </props> </property> <property name="jtaTransactionManager"> <ref bean="jotm" /> </property> </bean> <bean id="adminDAO" class="com.ky.ssh.dao.AdminDAO"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> <bean id="userDAO" class="com.ky.ssh.dao.UserDAO"> <property name="sessionFactory"> <ref bean="sessionFactory2" /> </property> </bean> <bean id="service" class="com.ky.service.Service"> <property name="ad" ref="adminDAO"></property> <property name="ud" ref="userDAO"></property> </bean> <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" /> <!-- jtatransactionmanager容器 --> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="userTransaction" ref="jotm" /> </bean> <!-- 指定userTransaction属性引用JOTM本地实例 --> <!-- 定义事务管理器(声明式的事务) <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory2" /> </bean> --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="upd*" propagation="REQUIRED" /> <tx:method name="del*" propagation="REQUIRED" /> <tx:method name="*" propagation="read-only" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="interceptorPointCuts" expression="execution(* com.ky.service.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" /> </aop:config> <bean id="login" class="com.ky.action.Login"> <property name="service" ref="service"></property> </bean> </beans>
测试:
@Test
publicvoid Test{
ApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml");
Service s=(Service) ac.getBean("service");
s.addUserAndAdmin("ky","123");
}
可以成功插入数据至量数据库,若某一点出问题,可回滚
至此配置成功