当我们的项目中需要应用到多个数据源时,事务的管理就很重要了。而Spring的JTA事务就很好的帮助了我们进行了多数据源的事务处理。
通过集成JOTM,直接在Spring中使用JTA事务
JOTM(Java Open Transaction Manager)是ObjectWeb的一个开源JTA实现,它本身也是开源应用程序服务器JOnAS(Java Open Application Server)的一部分,为其提供JTA分布式事务的功能。
Spring 2.0附带的依赖类库中虽然包含jotm类库,但是并不完整,你可以到http://jotm.objectweb.org下载完全版的JOTM。
Spring为JOTM提供了一org.springframework.transaction.jta.JotmFactoryBean支持类,通过该支持类可以方便地创建JOTM本地实例。
下面我们通过实例来使用JTA事务:
1.从http://www.findjar.com中找到以下jar包添加到你的项目中:
jotm-core-2.1.5.jar
jotm-2.0.10.jar
carol-3.0.7.jar
carol-interceptors-1.0.1.jar
xapool-1.5.0.jar
jotm-carol-1.5.3.jar
jotm-core-2.1.5.jar
jotm-jrmp-stubs-2.0.10.jar
transactions-api-3.2.3.jar
atomikos-util-3.2.3.jar
transactions-jta-3.2.3.jar
transactions-3.2.3.jar
connector.jar
2.添加JOTM配置文件carol.properties,放到类路径下:
两种方法:(1).从carol-3.0.7.jar中复制carol-defaults.properties到项目中,将文件名改为carol.properties即可
(2).自已手动编写,配置文件内容如下:
#JNDI调用协议
carol.protocols=jrmp
#不使用CAROL JNDI封装器
carol.start.jndi=false
#不启动命名服务器
carol.start.ns=false
# Indicate if a protocol-independent environment is used.
# Otherwise the environment of the default protocol is used.
carol.multi.env = true
3.编写spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:ehcache="http://www.springmodules.org/schema/ehcache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springmodules.org/schema/ehcache http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd" default-autowire="byName" default-lazy-init="true"> <!-- ①JOTM本地实例--> <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" /> <!-- ②JTA事务管理器--> <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"><!--②-1:指定userTransaction属性--> <property name="userTransaction" ref="jotm" /> </bean> <!--③XAPool配置,内部包含了一个XA数据源,对应topicdb数据库--> <bean id="topicDS" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown"> <property name="dataSource"> <!--③-1:内部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/topicdb" /> </bean> </property> <property name="user" value="root" /> <property name="password" value="root" /> </bean> <!--④按照③相似的方式配置另一个XAPool,对应postdb数据库,--> <bean id="postDS" 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/postdb" /> </bean> </property> <property name="user" value="root" /> <property name="password" value="root" /> </bean> <!--⑤配置访问topicDB数据源的Spring JDBC模板--> <bean id="topicTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="topicDS" /> </bean> <!--⑥配置访问postDB数据源的Spring JDBC模板--> <bean id="postTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="postDS" /> </bean> <!--⑦基于topicTemplate数据源的topicDao--> <bean id="topicDao" class="com.spring.service.impl.TopicDaoImpl"> <property name="jdbcTemplate" ref="topicTemplate" /> </bean> <!--⑧基于postTemplate数据源的postDao--> <bean id="postDao" class="com.spring.service.impl.PostDaoImpl"> <property name="jdbcTemplate" ref="postTemplate" /> </bean> <!--⑨进行跨数据库JTA事务的业务类--> <bean id="bbtForum" class="com.spring.service.impl.BbtForumImpl"> <property name="topicDao" ref="topicDao" /> <property name="postDao" ref="postDao" /> </bean> <!--⑩对BbtForumImpl业务类中的@Transaction注解进行驱动--> <tx:annotation-driven transaction-manager="txManager" /> </beans>
上面的配置文件中是操作数据库表是用jdbcTemplate,这个我觉得不好用,缺点是不能用Hql语句,而下面的spring配置文件中使用的是HibernateDaoSupport,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:ehcache="http://www.springmodules.org/schema/ehcache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springmodules.org/schema/ehcache http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd" default-autowire="byName" default-lazy-init="true"> <bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" lazy-init="true" /> <!-- ///////////////////JOTM本地实例 ////////////////////////--> <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" /> <!-- ///////////////////JTA事务管理器 ////////////////////////--> <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="userTransaction" ref="jotm" /> </bean> <!-- ///////////////////jta管理数据源一 ////////////////////////--> <bean id="oneDS" 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://127.0.0.1:3306/topicdb" /> </bean> </property> <property name="maxSize"> <value>10</value> </property> <property name="user"> <value>root</value> </property> <property name="password"> <value>root</value> </property> </bean> <!-- ///////////////////jta管理数据源二 ////////////////////////--> <bean id="twoDS" 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://127.0.0.1:3306/postdb" /> </bean> </property> <property name="maxSize"> <value>10</value> </property> <property name="user"> <value>root</value> </property> <property name="password"> <value>root</value> </property> </bean> <bean id="userTarget" class="com.spring.service.impl.UserServiceTeImpl"> <property name="baseDao"> <ref bean="baseDao1" /> </property> </bean> <bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>com.spring.service.UserServiceTe </value> </property> </bean> <bean id="sessionFactory1" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="mappingResources"> <list> <value>com/spring/mappings/Post.hbm.xml</value> </list> </property> <property name="lobHandler" ref="lobHandler" /> <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /> <property name="dataSource" ref="twoDS"></property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.connection.isolation">3</prop> <prop key="show_sql">true</prop> <prop key="format_sql">true</prop> </props> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="mappingResources"> <list> <value>com/spring/mappings/Topic.hbm.xml</value> </list> </property> <property name="lobHandler" ref="lobHandler" /> <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" /> <property name="dataSource" ref="oneDS"></property> </bean> <!-- HIBERNATE数据库管理实现类 --> <bean id="baseDao1" class="com.spring.dao.BaseDaoImpl"> <property name="sessionFactory"> <ref bean="sessionFactory1" /> </property> </bean> <bean id="baseDao" class="com.spring.core.dao.impl.BaseDaoImpl"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" /> </beans>
完成上面的步骤后,你就可以进行测试了。我自己测试的是OK的