zoukankan      html  css  js  c++  java
  • Spring对JTA的支持

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

    Sping对JTA支持的三种方式:
      1. 直接集成JOTM提供JTA事务管理(无应用服务器支持,常用于单元测试)
      2. 引用应用服务器(如Tomcat)的JNDI数据源,间接实现JTA事务管理
      3. 使用特定于应用服务器的事务管理器,使用JTA事务的高级功能(Weblogic,Websphere)

    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/

  • 相关阅读:
    UVA 10462 Is There A Second Way Left?(次小生成树&Prim&Kruskal)题解
    POJ 1679 The Unique MST (次小生成树)题解
    POJ 2373 Dividing the Path (单调队列优化DP)题解
    BZOJ 2709 迷宫花园
    BZOJ 1270 雷涛的小猫
    BZOJ 2834 回家的路
    BZOJ 2506 calc
    BZOJ 3124 直径
    BZOJ 4416 阶乘字符串
    BZOJ 3930 选数
  • 原文地址:https://www.cnblogs.com/daichangya/p/12958548.html
Copyright © 2011-2022 走看看