`
y806839048
  • 浏览: 1077072 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

分布式事务处理两阶段提交实例2及注意

阅读更多

引言:
  Spring 通过AOP技术可以让我们在脱离EJB的情况下享受声明式事务的丰盛大餐。
  通过配合使用ObjectWeb的JOTM开源项目,在不需要Java EE应用服务器的情况下,Spring也可以提供JTA事务。

用框架的话只要配置好对个数据源,和工厂,公用一个JtaTransactionManager事物管理器(xa事物管理),一个事物中有多个不同数据库操作不同数据源(xa数据源)的时候会自动启用

两阶段提交,在加入事物标签的地方遇到任何异常就会自动回滚。

三种集成方式:

  1. 直接集成JOTM提供JTA事务管理(无应用服务器支持,常用于单元测试)

  2. 引用应用服务器(如Tomcat)的JNDI数据源,间接实现JTA事务管理

  3. 使用特定于应用服务器的事务管理器,使用JTA事务的高级功能(Weblogic,Websphere)

   (注意一) 以上方式配置大统小异,只是数据源配置不一样(专用的可用于分布式的数据源配置)xa数据源

    1,用了JOTM配置方式

    2,用了jndi数据源(见:博客:配置Tomcat JNDI数据源)

    3,AtomikosDataSourceBean(类Spring常规)

    4,还可以用常规的spring数据源但是要xa式的StandardXAPoolDataSource

 

 (注意二)当然事物管理也要用xa的事务管理器:

由于大部分服务器获取jta的方式都不尽相同,spring还针对不同的服务器提供了不同的jta实现,例如:

WebLogicJtaTransactionManager

WebSphereUowTransactionManager

OC4JJtaTransactionManager

JtaTransactionManager--》tomcat

 

 

(注意三)ibatis与hibernate是一样的,只需要将hibernate的sessionFactory部分更换一下(数据源,事物管理器都一样)

 

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

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

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

1.4. 在Spring配置文件中配置JOTM,并实现具体业务类
代码清单 1 applicationContext-jta.xml

复制代码
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" />
①JOTM本地实例 ②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" />
复制代码

 

代码清单 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());  
    }
}
复制代码

1.5. 在Spring中运行测试

复制代码
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........");  
    }  
}
复制代码

2. Spring引用Tomcat的 JTA事务
  Tomcat是Servlet容器,但它提供了JNDI的实现,
  因此用户可以象在Java EE应用程序服务器中一样,在Tomcat中使用JNDI查找JDBC数据源。
  在事务处理方面,Tomcat本身并不支持JTA,但是可以通过集成JOTM达到目的。
  (测试环境:Tomcat 5.5+JOTM 2.3)
2.1. 添加所需的JAR文件 
  将JOTM以下类包添加到<Tomcat安装目录>/common/lib目录中: 
    jotm.jar 
    jotm_jrmp_stubs.jar 
    jotm_iiop_stubs.jar 
    ow_carol.jar 
    jta-spec1_0_1.jar 
    jts1_0.jar 
    objectweb-datasource.jar 
    xapool.jar 
    howl.jar 
    connector-1_5.jar 
  同时,还需要添加相应数据库的JDBC驱动类包,例如MySQL的mysql.jar。

2.2. 配置JOTM 
  新建一个carol.properties配置文件,放置到<Tomcat安装目录>/common/classes目录下,配置文件内容如下:
    #JNDI调用协议 
    carol.protocols=jrmp 
    # 本地RMI调用 
    carol.jvm.rmi.local.call=true 
    # 不使用CAROL的JNDI封装器 
    carol.start.jndi=false 
    # 不启用命名服务器 
    carol.start.ns=false 
    # 命名工厂类 
    carol.jndi.java.naming.factory.url.pkgs=org.apache.naming 
    将carol.start.jndi设置为false,让JOTM不使用CAROL JNDI wrapper,从而可以避免类装载错误的发生。

2.3. 配置Tomcat环境,配置JNDI的数据源 
  在<Tomcat安装目录>/conf/context.xml文件中添加以下内容:

复制代码
<!-- ①:JNDI数据源 -->
<Resource name="jdbc/topicDS" auth="Container" type="javax.sql.DataSource" 
    factory="org.objectweb.jndi.DataSourceFactory"
    username="root"
    password="1234"
    driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3309/topicdb"
    maxActive="30"
    maxIdle="30" />

<!-- ①:JNDI数据源 -->
<Resource name="jdbc/postDS" auth="Container" type="javax.sql.DataSource" 
    factory="org.objectweb.jndi.DataSourceFactory"
    username="root"
    password="1234"
    driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3309/postdb"
    maxActive="30"
    maxIdle="30" />
        
<!-- ②JOTM JTA事务管理 -->
<Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60" /> 
复制代码

 

4. Spring中相应的配置

复制代码
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="
      http://www.springframework.org/schema/beans   
      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
      http://www.springframework.org/schema/tx 
      http://www.springframework.org/schema/tx/spring-tx-2.0.xsd   
      http://www.springframework.org/schema/jee 
      http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">

    <jee:jndi-lookup id="topicDS" jndi-name="java:comp/env/jdbc/topicDS" />
    <jee:jndi-lookup id="postDS" jndi-name="java:comp/env/jdbc/postDS" />
    <bean id="topicTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="topicDS" />
    </bean>
    <bean id="postTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="postDS" />
    </bean>
    <bean id="topicDao" class="com.baobaotao.dao.jdbc.TopicJdbcDao">
        <property name="jdbcTemplate" ref="topicTemplate" />
    </bean>
    <bean id="postDao" class="com.baobaotao.dao.jdbc.PostJdbcDao">
        <property name="jdbcTemplate" ref="postTemplate" />
    </bean>
    <bean id="bbtForum" class="com.baobaotao.service.impl.BbtForumImpl">
        <property name="topicDao" ref="topicDao" />
        <property name="postDao" ref="postDao" />
    </bean>
    
<bean id="txManager" 
  class="org.springframework.transaction.jta.JtaTransactionManager" />
    <tx:annotation-driven transaction-manager="txManager" />
</beans>
复制代码

 

3. 在特定应用服务器使用JTA

BEA WebLogic 
  在一个使用WebLogic 7.0、8.1或更高版本的环境中,你一般会优先选用特定于WebLogic的 WebLogicJtaTransactionManager 类
  来取代基础的 JtaTransactionManager 类。
  因为在WebLogic环境中,该类提供了对Spring事务定义的完全支持,超过了标准的JTA语义。
  你可以使用以下的配置达到目的:

<bean id="txManager" class="org.springframework.transaction.jta.WebLogicJtaTransactionManager"/> 

 

  它的特性包括:支持事务名,支持为每个事务定义隔离级别,以及在任何环境下正确地恢复事务的能力。

IBM WebSphere 
  在WebSphere 5.1、5.0和4.x环境下,你可以使用Spring的 WebSphereTransactionManagerFactoryBean 类。
  这是一个工厂类,通过WebSphere的 静态访问方法(每个版本的WebSphere中都不同)获取到JTA TransactionManager 实例。
  一旦通过工厂bean获取到JTA TransactionManager 实例,
  就可以使用该实例装配一个Spring的 JtaTransactionManager bean,
  它封装了JTA UserTransaction,提供增强的事务语义。

复制代码
<bean id="wsJtaTm"
    class="org.springframework.transaction.jta.WebSphereTransactionManagerFactoryBean" />
<bean id="transactionManager"
    class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager ref=" wsJtaTm " />
    <!--①引用WebSphere的JTA事务管理器-->
</bean>
复制代码

 

名称解释:
  JOTM(Java Open Transaction Manager)是ObjectWeb的一个开源JTA实现,
  它本身也是开源应用程序服务器JOnAS(Java Open Application Server)的一部分,
  为其提供JTA分布式事务的功能。 

参考:
JTA事务管理(一)http://mavin.zhou.blog.163.com/blog/static/114522435200971822334475/
JTA事务管理(二)http://mavin.zhou.blog.163.com/blog/static/114522435200971822912342/

 

其它:
JTA集成JOTM或Atomikos配置分布式事务(Tomcat应用服务器) http://kb.cnblogs.com/a/2012014/

分享到:
评论

相关推荐

    分布式事务实践 解决数据一致性

    还有XA以及两阶段提交,并通过实例演示了使用JTA,通过两阶段提交,实现多数据源的事务实现。... 4-1 Spring事务机制_基本接口 4-2 Spring事务机制_实现 4-3 Jpa事务实例 4-4 Jms事务原理 4-5 Jms-session事务实例 4...

    消除分布式事务的方法

    由于数据量的巨大,大部分Web应用都需要部署很多个数据库实例。这样,有些用户操作就可能需要去修改多个数据库实例中的数据。传统的解决方法是使用分布式事务保证数据的全局一致性,经典的方法是使用两阶段提交协议^

    Atomikos3.9官方包文档以及实例

    XA协议采用两阶段提交方式来管理分布式事务。XA接口提供资源管理器与事务管理器之间进行通信的标准接口。XA协议包括两套函数,以xa_开头的及以ax_开头的。 以下的函数使事务管理器可以对资源管理器进行的操作: 1)...

    三层C/S结构编程指南

    本书详细介绍了三层客户机服务器结构的系统结构,从计算机体系结构的变迁,三层结构的优点,一些常见概念,如数据的一致性、两阶段提交、分布式事务处理、事务处理器以及XA规范的系统说明,到CICS是如何构造以...

    数据库系统-招标参数---模板.doc

    具有多种复制功能模块 " " " "支持ODBC 3.0、X/Open XA、CLI、JDBC等标准 " " " "支持分布式事务及两阶段提交功能 " " " "支持动态将锁粒度调整到合适的级别,支持动态行" " " "级锁定 " " " "支持高可用性组,可以...

    ORACLE9i_优化设计与系统调整

    §9.7.1 在线事务处理(OLTP) 108 §9.7.2 决策支持系统(DSS) 109 §9.7.3 多用途应用程序 109 §9.8 注册应用程序 109 §9.9 Oracle配置 110 §9.9.1 分布式系统 110 §9.9.2 多层系统 110 §9.9.3 Oracle并行服务器...

    oracle数据库dba管理手册

    7.1.3 为事务处理指定回滚段 169 7.2 回滚段的空间使用 169 7.3 监控回滚段使用 173 7.3.1 监控当前空间分配 173 7.3.2 收缩回滚段 173 7.3.3 监控当前状态 174 7.3.4 监控动态扩展 174 7.3.5 每个回滚段中的事务 ...

    基于J2EE框架的个人博客系统项目毕业设计论文(源码和论文)

    因此,在具体设计实现该博客网站时,主要考虑了主流博客网站的几个主要功能:(1)博客的注册、登录验证功能(2) 网络用户通过关键字搜索博文功能(3) 最热门博客页面推荐浏览(4) 文章详细内容及相关评论显示(5) 博客...

    trip-booking-saga-java:使用轻量级开源工作流引擎(Camunda)的经典旅行预订示例的Saga模式的示例实现

    佐贺市的例子:旅行预订Saga模式描述了如何在没有两阶段提交的情况下解决分布式(业务)事务,因为这在分布式系统中无法扩展。 基本思想是将整个交易分为多个步骤或活动。 Saga只能在原子事务中执行内部步骤,但是...

    Hadoop权威指南(中文版)2015上传.rar

    Nutch系统利用Hadoop进行数据处理的精选实例 总结 Rackspace的日志处理 简史 选择Hadoop 收集和存储 日志的MapReduce模型 关于Cascading 字段、元组和管道 操作 Tap类,Scheme对象和Flow对象 Cascading实战 灵活性 ...

    Hadoop权威指南 第二版(中文版)

     Nutch系统利用Hadoop进行数据处理的精选实例  总结  Rackspace的日志处理  简史  选择Hadoop  收集和存储  日志的MapReduce模型  关于Cascading  字段、元组和管道  操作  Tap类,Scheme对象和Flow对象 ...

Global site tag (gtag.js) - Google Analytics