首页 > 其他分享 >Spring 中集成 JOTM 配置 JTA 事务

Spring 中集成 JOTM 配置 JTA 事务

时间:2023-08-28 14:04:36浏览次数:54  
标签:JOTM grade Spring public com user import JTA id


假如业务中要用到多个数据库,我们希望在业务方法中,当对某一个数据库的数据表进行操作的事务失败并回退(rollback),另外某一个数据库的数据表的操作事务也要回退,但应用一般的事务管理达不到这样的事务管理效果,这就需要实现 JTA 事务管理了。
这里我们在SPring中集成 Object web 的一个开源JTA实现JOTM (可以在http://jotm.objectweb.org下载完整版) 来实现JTA事务管理。

1、将必须的类包放入类路径中:
 jotm.jar, xapool.jar, jotm_jrmp_stubs.jar, jta-spect1_0_1.jar, connector-1_5.jar等等。

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

 
3、在MYSQL中创建两个数据库 "jtatesta","jtatestb":
Java代码

CREATE DATABASE IF NOT EXISTS jtatesta;  
USE jtatesta;  
  
DROP TABLE IF EXISTS `user`;  
CREATE TABLE `user` (  
  `user_id` int(10) unsigned NOT NULL auto_increment,  
  `user_name` varchar(45) NOT NULL,  
  `user_password` varchar(45) NOT NULL,  
  PRIMARY KEY  (`user_id`)  
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;  
  
INSERT INTO `user` (`user_id`,`user_name`,`user_password`) VALUES   
 (1,'tufu','tufu');  
  
CREATE DATABASE IF NOT EXISTS jtatestb;  
USE jtatestb;  
  
DROP TABLE IF EXISTS `grade`;  
CREATE TABLE `grade` (  
  `grade_id` int(10) unsigned NOT NULL auto_increment,  
  `user_id` int(10) unsigned NOT NULL,  
  `grade` double NOT NULL,  
  PRIMARY KEY  (`grade_id`)  
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;  
  
INSERT INTO `grade` (`grade_id`,`user_id`,`grade`) VALUES   
 (1,0,100);

 
4、域对象、数据访问类和其他事务管理的一样,如:
Java代码

//Domain对象User.java:  
package com.domain;  
import java.io.Serializable;  
public class User implements Serializable {  
    private int user_id;  
    private String user_name;  
    private String user_password;  
......//省略set、get方法  
}  
  
//Domain对象Grade.java:  
package com.domain;  
import java.io.Serializable;  
public class Grade implements Serializable{  
    private int grade_id;  
    private User user;  
    private double grade;  
.....//省略set、get方法  
}


应用Spring JDBC的DAO:(省略DAO接口) 
//UserJdbcDao.java: 

package com.dao.jdbc;  
import org.springframework.jdbc.core.support.JdbcDaoSupport;  
import com.dao.UserDao;  
import com.domain.User;  
public class UserJdbcDao extends JdbcDaoSupport implements UserDao{  
    public void addUser(User user){  
        String SQL = "INSERT INTO user(user_id,user_name,user_password) VALUES(?,?,?)";  
        Object[] params = new Object[]{  
            user.getUser_id(),user.getUser_name(),user.getUser_password()  
        };  
        this.getJdbcTemplate().update(SQL, params);  
    }  
}  
//GradeJdbcDao.java:  
package com.dao.jdbc;  
import com.dao.GradeDao;  
import com.domain.Grade;  
import org.springframework.jdbc.core.support.JdbcDaoSupport;  
public class GradeJdbcDao extends JdbcDaoSupport implements GradeDao{  
    public void addGrade(Grade grade){  
        final String SQL = "INSERT INTO grade(user_id,grade) VALUES(?,?)";  
        Object[] params = new Object[]{  
            grade.getUser().getUser_id(),grade.getGrade()  
        };  
        this.getJdbcTemplate().update(SQL, params);  
    }  
}

 
5、应用了JTA事务管理的业务类(省略了接口),用@Transactional注解标注,以在配置文件中可以用<tx:annotation-driven>注解驱动自动进行事务增强:
Java代码

package com.service.impl;  
import com.dao.GradeDao;  
import com.dao.UserDao;  
import com.domain.*;  
import org.springframework.transaction.annotation.Transactional;  
import com.service.MyService;  
@Transactional  
public class MyServiceImpl implements MyService {  
    private UserDao userDao;  
    private GradeDao gradeDao;  
    public void setUserDao(UserDao userDao){  
        this.userDao = userDao;  
    }  
    public void setGradeDao(GradeDao gradeDao){  
        this.gradeDao = gradeDao;  
    }  
    @Transactional(readOnly=false)  
    public void addGrade(User user,Grade grade){  
        //假如希望两个添加数据的事务,其中有一个添加失败时,均回滚,  
        //由于两个操作是在两个不同的数据库上进行的,故要JTA事务来进行管理  
        //否则,将会出现添加一个,回滚一个的情形  
        gradeDao.addGrade(grade);   
        userDao.addUser(user);  
    }  
}


6、spring为JOTM提供了一个org.springframework.transaction.jta.JotmFactoryBean 支持类,可以用其方便地创建本地JOTM实例。
具体的配置文件app_jta.xml如下:
Xml代码

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsp="http://www.w3.org/2001/XMLSchema-instance"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xsp:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  
    http://www.springframework.org/schema/aop  
    http://www.springframework.org/schema/aop/spring-aop-2.0.xsd  
    http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  
   <!--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"/><!--指定userTransaction属性引用JOTM本地实例-->  
    </bean>  
    <!--XAPool配置,内部包含了一XA数据源,对应了数据库jtatesta  
    支持JTA事务的数据源,必须封装成XAPool-->  
    <bean id="jtaTestADS" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"  
    destroy-method="shutdown">  
        <property name="dataSource"><!--内部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/jtatesta"/>  
            </bean>  
        </property>  
        <property name="user" value="root"/>  
        <property name="password" value="885123"/>  
    </bean>  
    <!--类似地,对应了数据库jtatestb的XAPool配置,内部包含了一XA数据源-->  
    <bean id="jtaTestBDS" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"  
    destroy-method="shutdown">  
        <property name="dataSource"><!--内部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/jtatestb"/>  
            </bean>  
        </property>  
        <property name="user" value="root"/>  
        <property name="password" value="885123"/>  
    </bean>  
  
    <!--分别配置访问jtaTestADS、jtaTestBDS数据源的Spring JDBC模板-->  
    <bean id="jtaTestATemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
        <property name="dataSource" ref="jtaTestADS"/>  
    </bean>  
    <bean id="jtaTestBTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
        <property name="dataSource" ref="jtaTestBDS"/>  
    </bean>  
  
    <!--分别配置基于模板jtaTestADS,jtaTestBDS的DAO-->  
    <bean id="userDao" class="com.dao.jdbc.UserJdbcDao">  
        <property name="jdbcTemplate" ref="jtaTestATemplate"/>  
    </bean>  
    <bean id="gradeDao" class="com.dao.jdbc.GradeJdbcDao">  
        <property name="jdbcTemplate" ref="jtaTestBTemplate"/>  
    </bean>  
  
    <!--跨数据库的JTA事务的业务类-->  
    <bean id="myService" class="com.service.impl.MyServiceImpl">  
        <property name="userDao" ref="userDao"/>  
        <property name="gradeDao" ref="gradeDao"/>  
    </bean>  
 <!--注解事务驱动-->  
    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>  
  
</beans>

7、测试main方法:
Java代码

import com.service.MyService;  
import com.service.impl.MyServiceImpl;  
import com.domain.*;  
import org.springframework.context.support.ClassPathXmlApplicationContext;  
  
public class TestMain {  
    public static void main(String args[]){  
        ClassPathXmlApplicationContext ctx =  
                new ClassPathXmlApplicationContext("beans_jta.xml");  
        MyService ms = (MyServiceImpl)ctx.getBean("myService");  
        User user = new User();  
//特意添加一个重复的主键,以使添加user的事务失败并回退  
//如果此时应用JTA事务失败,将仍会执行添加grade的事务并提交(前提是先于添加user操作)  
//如果应用JTA事务成功,就会两个添加事务同时执行或同时回退。  
        user.setUser_id(1);   
        user.setUser_name("tufu");  
        user.setUser_password("tufu");  
        Grade grade = new Grade();  
        grade.setGrade(100);  
        grade.setUser(user);  
  
        ms.addGrade(user,grade);  
    }  
}


  

 注:将log4j.properties中的log4j日志设置为DEBUG级别,可以看到详细的JTA事务执行情况:
.......
log4j.rootLogger=DEBUG,R,A1

 

标签:JOTM,grade,Spring,public,com,user,import,JTA,id
From: https://blog.51cto.com/u_16237557/7263414

相关文章

  • Spring5框架-cnblog
    Spring5框架基础使用:JavaBean目的解决企业应用开发的复杂性功能:使用基本的JavaBean代替EJB,本身是一个大杂烩,整合了现有的技术框架范围:任何Java应用Spring框架以interface21框架为基础,经过重新设计,不断丰富,于2001年发布1.0正式版,轻量级的控制反转(IOC)h和面向切......
  • 基于springboot的校园二手交易市场管理系统研究-计算机毕业设计源码+LW文档
    一、设计(论文)选题的依据(选题的目的和意义、该选题在国内外的研究现状及发展趋势,等)在国家倡导节能减排背景下,节俭消费理念已逐渐成为人们生活的主流观念。特别是在现阶段,国家发展仍是以经济建设为核心,所以在保障经济发展的前提下,对社会对环境保持友好的态度下,协调好人类与环境的共......
  • [完结13章]SpringBoot打造企业级一体化SaaS系统
    点击下载——[完结13章]SpringBoot打造企业级一体化SaaS系统提取码:p8kmSpringBoot打造企业级一体化SaaS系统教程,已完结13章下载,附源码!1、什么是saas系统?SaaS提供商为企业搭建信息化所需要的所有网络基础设施及软件、硬件运作平台,并负责所有前期的实施、后期的维护等一系列服务,......
  • SpringBoot常用注解
    前段时间学习了SpringBoot这个快速开发框架,觉得这个框架写的真的是太优秀了,尤其是SpringBoot的自动配置机制,真的是过于强大,它使我们不再需要定义样板化的配置,大大提高了程序的开发效率。在这点上,我需要解释的是SpringBoot其实是对Spring和SpringMVC框架的再封装。那么,有的......
  • Spring3中替换默认拦截器的方法BeanFactoryPostProcessor
    由于Spring默认的静态资源处理器不能满足需求,需要做一些自己的处理,但mvc:resources的标签又挺好用的,不想每次配置静态资源目录的时候,还要特殊指定处理器,也不想修改任何配置代码,于是找到了使用BeanFactoryPostProcessor的方法 实现代码如下:importorg.springframework.beans.Beans......
  • 在spring、tomcat中使用多数据源并支持分布式事务管理
    题目起得有点模糊,第一次接触这东西,还不怎么理解。 起因: 小项目,没有用分布式,但要操作两个数据库。本以为随便用spring配置两个数据源就搞定,查询是没问题,问题是有一个数据库老是插不进数据。Google狂搜之后,大概了解到是事务控制的问题。我用的是spring的声明式事务管理(<tx:annotat......
  • SpringMVC3的ResponseBody返回字符串乱码问题解决
    SpringMVC的@ResponseBody注解可以将请求方法返回的对象直接转换成JSON对象,但是当返回值是String的时候,中文会乱码 原因是因为其中字符串转换和对象转换用的是两个转换器,而String的转换器中固定了转换编码为"ISO-8859-1" 网上也很多种解决方法,有通过配置Bean编码的,也有自己重写转......
  • 在SpringBoot中使用WebSocket
    一、概述最近在SpringBoot中用到了WebSocket的功能,在此记录一下使用步骤。SpringBoot使用WebSocket还是比较简单的,只需要4步就行了。如下二、使用步骤第一步:在pom.xml文件中导入坐标<!--websocketdependency--><dependency><grou......
  • 基于SpringBoot的保险合同管理系统的设计与实现
    现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本可盈保险合同管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事......
  • 基于springboot校园失物招领系统
    身处网络时代,随着网络系统体系发展的不断成熟和完善,人们的生活也随之发生了很大的变化,身边经常有同学丢失了东西或者衣服而烦恼,为了找到自己心爱的物品疲于奔命,还不一定能找到,为了满足学生失物招领的要求,校园失物招领系统被开发研究了出来。本文主要描述了该校园失物招领系统的具体......