概述 
   【IT168 专稿】Spring 通过AOP技术可以让我们在脱离EJB的情况下享受声明式事务的丰盛大餐,脱离Java EE应用服务器使用声明式事务的道路已经畅通无阻。但是很大部分人都还认为脱离Java EE应用服务器就无法使用JTA事务,这是一个误解。其实,通过配合使用ObjectWeb的JOTM开源项目,不需要Java EE应用服务器,Spring也可以提供JTA事务。

正因为AOP让Spring拥有了脱离EJB容器的声明式事务能力,而JOTM让我们在脱离Java EE应用服务器下拥有JTA事务能力。所以,人们将AOP和JOTM称为Java软件开发的两个圣杯。

本文将讲解Spring在不同环境下提供JTA事务的配置过程,这包括:Spring中直接集成JOTM提供JTA事务管理、将JOTM集成到Tomcat中,Spring通过引用Tomcat JNDI数据源提供JTA事务管理、引用其它功能完善JavaEE应用服务器所提供的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本地实例。

下面,我们通过配置,使上节中BbtForumImpl#addTopic()方法工作在JTA事务的环境下。addTopic()内部使用两个DAO类(TopicDao和PostDao)分别访问不同数据库中的表。通过下面的步骤说明了使addTopic()方法拥有JTA事务的整个过程:

1. 将JOTM以下类库添加到类路径中: 
    jotm.jar 
    xapool.jar 
    jotm_jrmp_stubs.jar 
    jta-spec1_0_1.jar 
    connector-1_5.jar

2. 编写JOTM配置文件,放到类路径下 
    carol.properties 
    #JNDI调用协议 
    carol.protocols=jrmp 
    #不使用CAROL JNDI封装器 
    carol.start.jndi=false 
    #不启动命名服务器 
    carol.start.ns=false

3. 在MySQL上建立两个数据库 
    在MySQL数据库中运行SQL脚本,建立topicdb和postdb两个数据库,在topicdb数据库中创建t_topic表,在postdb数据库中创建t_post表。我们希望在这两个数据库上进行JTA事务。

4. 在Spring配置文件中配置JOTM 
    代码清单 1 applicationContext-jta.xml 
    …

<!--①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" /> <!--②-1:指定userTransaction属性-->
</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:3309/topicdb" />
</bean>
</property>
<property name="user" value="root" />
<property name="password" value="1234" />
</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:3309/postdb" />
</bean>
</property>
<property name="user" value="root" />
<property name="password" value="1234" />
</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.baobaotao.dao.jdbc.TopicJdbcDao">
<property name="jdbcTemplate" ref="topicTemplate" />
</bean>
<!--⑧基于postTemplate数据源的postDao -->
<bean id="postDao" class="com.baobaotao.dao.jdbc.PostJdbcDao">
<property name="jdbcTemplate" ref="postTemplate" />
</bean>
<!--⑨进行跨数据库JTA事务的业务类-->
<bean id="bbtForum" class="com.baobaotao.service.impl.BbtForumImpl">
<property name="topicDao" ref="topicDao" />
<property name="postDao" ref="postDao" />
</bean>
<!--⑩对BbtForumImpl业务类中的@Transaction注解进行驱动,以织入事务管理切面 -->
<tx:annotation-driven transaction-manager="txManager" />

首先,我们在①处通过Spring所提供的JotmFactoryBean创建一个本地JOTM实例,该实例同时实现了   javax.transaction.UserTransaction和javax.transaction.TransactionManager接口,它可以和ObjectWeb的XAPool一起工作。 
JTA事务管理器通过userTransaction属性引用本地JOTM实例,Spring的JtaTransactionManager会自动探测到传入的javax.transaction.UserTransaction引用也实现了javax.transaction.TransactionManager,所以我们无需再配置JtaTransactionManager的transactionManager属性,如②所示。 
     在Spring中配置JOTM的另一个关键问题是配置XAPool,支持JTA事务的数据源必须封装成XAPool。首先,我们通过org.enhydra.jdbc.standard.StandardXADataSource 配置一个XA数据源,它指向topicdb数据库,如③-1所示。而后,通过org.enhydra.jdbc.pool.StandardXAPoolDataSource将其封装成一个XAPool,如③所示。按照相同的方式,配置指向postdb数据库的XAPool,如④所示。 
     接下来的配置就顺理成章了,分别使用Spring JDBC的模板类配置DAO类,然后再配置引用DAO类的业务类。关于Spring JDBC的详细内容,参见第10章的内容。 
     这里,我们使用@Transaction注解对业务类BbtForumImpl进行事务声明,所以通过<tx:annotation-driven/>对此进行驱动,BbtForumImpl的代码如下所示: 
代码清单 2 BbtForumImpl

package com.baobaotao.service.impl;
import org.springframework.transaction.annotation.Transactional;
import com.baobaotao.dao.PostDao;
import com.baobaotao.dao.TopicDao;
import com.baobaotao.domain.Forum;
import com.baobaotao.domain.Topic;
import com.baobaotao.service.BbtForum;
@Transactional// ①事务注解,以便Spring动态织入事务管理功能
public class BbtForumImpl implements BbtForum {
private TopicDao topicDao;
private PostDao postDao; public void addTopic(Topic topic) throws Exception {
//②将方法将被施加JTA事务的增强
topicDao.addTopic(topic);
postDao.addPost(topic.getPost());
}
}

BbtForumImpl将Dao类组织起来,PostDao和TopicDao分别访问不同数据库中表,通过Spring注解驱动事务切面的增强后,它们将工作于同一个JTA事务中。

    5. 在Spring中运行测试 
    代码清单 3 TestBbtForumJta

package com.baobaotao.service;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests; public class TestBbtForumJta extends AbstractDependencyInjectionSpringContextTests{ private BbtForum bbtForum;
private final Logger logger = Logger.getLogger(getClass()); public void setBbtForum(BbtForum bbtForum) {
this.bbtForum = bbtForum;
} protected String[] getConfigLocations() {
return new String[]{"classpath:applicationContext-jta.xml"};
} public void testAddPost() throws Exception{
logger.info("begin........");
Topic topic = new Topic();
topic.setTopicTitle("Title -pfb");
Post post = new Post();
post.setPostText("post content -pfb");
topic.setPost(post);
bbtForum.addTopic(topic);
//①使用了JTA事务的业务方法
logger.info("end........");
}
}

通过Spring测试类AbstractDependencyInjectionSpringContextTests的支持,很容易编写一个测试类,对启用了JTA事务的BbtForum#addTopic()方法进行测试。建议你将Log4J设置为DEBUG,这样就可以通过丰富的输出日志观测到JTA事务的执行情况。运行这个测试类后,你将可以看到JTA事务被正确实施。

JTA事务管理--配置剖析的更多相关文章

  1. JTA事务管理--配置剖析(二)

    Spring引用Tomcat的 JTA事务     Tomcat是Servlet容器,但它提供了JNDI的实现,因此用户可以象在Java EE应用程序服务器中一样,在Tomcat中使用JNDI查找JD ...

  2. springboot多数据源+jta事务管理配置

    1.创建一个maven项目,导入相关配置: <?xml version="1.0" encoding="UTF-8"?> <project x ...

  3. spring,mybatis事务管理配置与@Transactional注解使用[转]

    spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是至关 ...

  4. JTA事务管理

    何为分布式事务 一个事务包含多个操作,多个操作操作了多个数据源,这样的事务称为分布式事务 和普通事务的区别 单一数据源,事务管理可以借助数据源本地事务完成,实现简单 分布式事务之困难:不可简单的借助数 ...

  5. 事务管理配置与@Transactional注解使用

    spring,mybatis事务管理配置与@Transactional注解使用 概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性. Spring Framewor ...

  6. spring,mybatis事务管理配置与@Transactional注解使用

    spring,mybatis事务管理配置与@Transactional注解使用[转]   spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是 ...

  7. Spring事务管理配置以及异常处理

    Spring事务管理配置: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=" ...

  8. [转]Spring的事务管理难点剖析(1):DAO和事务管理的牵绊

    原文地址:http://stamen.iteye.com/blog/1441758 有些人很少使用Spring而不使用Spring事务管理器的应用,因此常常有人会问:是否用了Spring,就一定要用S ...

  9. spring3.0事务管理配置

    转载:http://war-martin.iteye.com/blog/1396335 第一种配置方法:基于XML的事务管理 这种方法不需要对原有的业务做任何修改,通过在XML文件中定义需要拦截方法的 ...

随机推荐

  1. POJ 3579

    Median Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3528   Accepted: 1001 Descriptio ...

  2. JAVASCRIPT的一些知识点梳理

    春节闲点,可以安心的梳理一下以前不是很清楚的东东.. 看的是以下几个URL: http://web.jobbole.com/82520/ http://blog.csdn.net/luoweifu/a ...

  3. [杂题]URAL2047. Maths

    题意:构造一个长度为n的串,使得 除了第一个以外,每个位置的前缀和的因子个数恰好等于该位置上的数. n$\le 100000$ 举个例子$a_i$:2   4    6     6    4    8 ...

  4. ubuntu 13.10 64bit装BeyondCompare

    1. Beyond Compare官网下载amd-64位的,安装失败,依赖于ia32-libs,但是这个文件已经不在源里了: 2. 官网下载tar.gz源码包,解压安装失败: 3. 直接装32位的,可 ...

  5. 从SQL Server中导入/导出Excel的基本方法(转)

    从sql server中导入/导出 excel 的基本方法 /*=========== 导入/导出 excel 的基本方法 ===========*/ 从excel文档中,导入数据到sql数据库中,很 ...

  6. 猜拳 GuessFist

    import java.util.Scanner;import java.util.Random;/***跟电脑玩石头剪刀布,需要从控制台输入信息,*然后去判断,然后给予反馈信息*/public cl ...

  7. 40. Combination Sum II

    题目: Given a collection of candidate numbers (C) and a target number (T), find all unique combination ...

  8. 剖析MapReduce 作业运行机制

    包含四个独立的实体: ·  Client Node 客户端:编写 MapReduce代码,配置作业,提交MapReduce作业. ·  JobTracker :初始化作业,分配作业,与 TaskTra ...

  9. 对Memcached使用的总结和使用场景

    1.memcached是什么 Memcached 常被用来加速应用程序的处理,在这里,我们将着重于介绍将它部署于应用程序和环境中的最佳实践.这包括应该存储或不应存储哪些.如何处理数据的灵活分布以 及如 ...

  10. C Socket Programming for Linux with a Server and Client Example Code

    Typically two processes communicate with each other on a single system through one of the following ...