• 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/

  • 相关阅读:
    less @import and extend及mixin详解
    Less的guards and argument matching
    LESS嵌套中的Mixins和classes
    bootstrap colorscheme以及theme自动生成
    C# Winform 获得下拉框 选中的值
    C# 后台按键 视频播放器 全屏后无法 触发
    C# 调用win32API 获取进程句柄 有毛用???
    C# 键盘钩子
    C# SqlParameter 使用
    C# 获得星期几
  • 原文地址:https://www.cnblogs.com/daichangya/p/12958548.html
Copyright © 2020-2023  润新知