`

Spring 中集成 JOTM 配置 JTA 事务

    博客分类:
  • Java
阅读更多

假如业务中要用到多个数据库,我们希望在业务方法中,当对某一个数据库的数据表进行操作的事务失败并回退(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

 

分享到:
评论

相关推荐

    Spring+iBatis+JOTM实现JTA事务

    通过这样的配置和测试,我们可以验证Spring+iBatis+JOTM的JTA事务管理功能是否正常工作。这种方式特别适用于需要在非J2EE容器中实现分布式事务的场景,为应用提供了强大的事务管理能力。然而,需要注意的是,JTA事务...

    spring JTA集成JOTM或Atomikos配置分布式事务(Tomcat应用服务器)

    3. **Spring配置**:在Spring的配置文件中,使用`jee:jta-data-source`或`jee:resource-ref`元素来引用之前创建的JNDI数据源,并配置`PlatformTransactionManager`为`org.objectweb.jotm.CurrentJOTM`。 **Atomikos...

    spring + JTA + JOTM实现分布式事务

    对于分布式事务,Spring支持JTA事务管理,并且可以无缝集成JOTM。 1. **配置JOTM**:首先,你需要在项目的类路径下添加JOTM的依赖库。然后,在Spring的配置文件中定义JOTM的事务管理器 bean,例如: ```xml ...

    多数据源 更新 spring jta java jotm

    要在Spring中配置JOTM,首先添加JOTM和Spring的JTA依赖到项目中。然后,定义一个`PlatformTransactionManager` bean,使用`JotmFactoryBean`来创建JOTM实例。这样,Spring就可以利用JOTM管理事务,确保在多数据源...

    在Spring中使用JTA事务管理

    本文将详细介绍如何在Spring中使用JTA事务管理,包括通过集成JOTM(Java Open Transaction Manager)以及引用Tomcat的JTA事务。 ### 1. 通过集成JOTM,直接在Spring中使用JTA事务 #### 1.1. 添加JOTM类库到类路径...

    Java分布式开发spring+jta+jotm

    JOTM可以在Spring框架中无缝集成,通过Spring的PlatformTransactionManager接口来配置和使用。 **Spring 配置JTA和JOTM** 在Spring中使用JTA和JOTM,首先需要在项目中引入JOTM的依赖。接着,你需要配置Spring的`...

    spring+jotm 多数据源事务管理(二)hibernate

    在Spring中集成JOTM可以提供更高级别的事务控制,确保在多数据源环境下事务的一致性和完整性。 首先,我们需要了解在没有使用JOTM时,Spring与Hibernate的常规配置。在提供的XML配置代码中,可以看到Spring配置了一...

    Spring+JOTM 分布式事务管理

    Spring框架作为一个广泛使用的Java应用程序开发框架,提供了多种支持事务管理的解决方案,其中包括集成JOTM(Java Open Transaction Manager)来处理分布式事务。本文将深入探讨Spring与JOTM结合使用的知识点,帮助...

    spring 3.0.5 + jotm 实现的的spring mvc 的例子

    在Spring中,通过集成JOTM,可以实现全局的事务控制,确保在多资源操作中保持数据的一致性。 **集成步骤**: 1. **添加依赖**:首先,项目需要在构建配置(如pom.xml或build.gradle)中引入Spring 3.0.5和JOTM的...

    spring+jotm 多数据源事务管理(三)JNDI+Tomcat

    在Tomcat中配置JNDI资源,以便Spring可以使用这些数据源。具体的XML配置如下: ```xml auth="Container" factory="org.objectweb.jndi.DataSourceFactory" type="javax.sql.DataSource" driverClassName=...

    spring-hibernate-jotm 例子

    而“jotm-2.0.10”则是JOTM的具体版本,包含其核心组件和必要的依赖,用于在Spring环境中配置和使用JOTM。 为了运行这个示例,你需要将这些jar包添加到你的项目类路径中,然后配置Spring的事务管理器为JOTM,并配置...

    Spring分布式事务实现

    在Spring中集成JOTM,可以利用其功能来管理跨数据库的事务。 JOTM相关的jar包包括`jotm-core.jar`,`xapool.jar`,`ow2-connector-1.5-spec.jar`和`ow2-jta-1.1-spec.jar`。这些库提供了JOTM的核心实现和连接池支持...

    使用JOTM实现分布式事务管理(多数据源)

    此外,JOTM还支持与Spring框架的集成,可以轻松地在Spring应用上下文中配置和管理事务。通过使用`@Transactional`注解,开发者可以在方法级别声明事务,简化事务管理。 总之,JOTM是实现Java分布式事务管理的强大...

    JOTM简单测试DEMO(不含jar包)

    这个DEMO可以帮助开发者理解如何在实际项目中集成JOTM和Spring进行分布式事务处理。需要注意的是,虽然DEMO中没有包含jar包,但你仍需自行获取并添加到项目中,否则无法正常运行。在实践中,根据具体的业务需求和...

    分布式事务JTA之实践:Spring+ATOMIKOS

    在实践过程中,首先需要在Spring配置文件中配置Atomikos事务管理器,包括设置事务超时时间、事务日志路径等参数。然后,为需要参与事务操作的数据源或消息队列注册为XAResources。接着,通过Spring的`@Transactional...

    Spring框架技术

    4. 使用Spring的事务注解或XML配置来指定哪些方法需要在JTA事务中执行。例如,假设有一个名为BbtForumImpl的类,其中的addTopic()方法需要在事务中运行,那么可以使用@Transactional注解标记这个方法,或者在Spring...

    开源事务管理器 JOTM.7z

    在实际应用中,JOTM 可能会与诸如 Spring 框架等进行整合,Spring 提供的事务管理抽象层使得与 JOTM 的集成变得更加简单。开发者可以利用 Spring 的 `@Transactional` 注解来自动管理事务的边界,提高代码的可读性...

    spring对多个数据库进行事务管理.doc

    在Spring中配置多个数据源并进行事务管理,可以参考以下步骤: 1. **配置数据源**:为每个数据库创建一个数据源Bean,例如`dataSource1`和`dataSource2`。这些数据源可以是基于JDBC的,也可以是其他ORM框架如...

    jotm 的 jar

    在JOTM的场景中,Spring可以用来配置和管理事务边界,通过声明式事务管理,使得在应用代码中无需显式调用事务开始和结束,而是由Spring自动处理,提高了代码的可读性和可维护性。 将这些组件整合在一起,开发者可以...

Global site tag (gtag.js) - Google Analytics