`
mrzhangtufu
  • 浏览: 60586 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Spring 集成 JOTM 的 JTA 事务管理

阅读更多

Spring 中集成 JOTM 配置 JTA 事务:

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

#JNDI调用协议
carol.protocols=jrmp
#不使用CAROL JNDI封装器
carol.start.jndi=false
#不启动命名服务器
carol.start.ns=false

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

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、域对象、数据访问类和其他事务管理的一样,如:

//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>注解驱动自动进行事务增强:

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 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方法:

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
.......

6
0
分享到:
评论
3 楼 yqzy_87050801 2012-06-05  
@Transactional
不起作用啊
2 楼 mrzhangtufu 2009-07-29  
I'm so sorry! 我的这些资料已经找不回来了~~~~我自己想找回来看看都没机会了!
1 楼 kidfang 2009-06-05  
楼主能贴出beans_jta.xml吗, 我正在学习事务,一直没成功,麻烦楼主发个完整的WAR包好吗. kidfang@21cn.com                     
                                        致敬!

相关推荐

    在Spring中使用JTA事务管理

    在Spring中使用JTA事务管理 1 通过集成JOTM,直接在Spring中使用JTA事务 1.1. 将JOTM以下类库添加到类路径中 1.2. 编写JOTM配置文件,放到类路径下 1.3. 在MySQL上建立两个数据库 1.4. 在Spring配置文件中配置JOTM ...

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

    NULL 博文链接:https://zhaoshijie.iteye.com/blog/1836707

    java开源包1

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包11

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包2

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包3

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包6

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包5

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包10

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包4

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包8

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包7

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包9

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    java开源包101

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    Java资源包01

    JFile 是 JActor 的文件持久化组件,以及一个高吞吐量的可靠事务日志组件。 Google地图JSP标签库 利用Google:maps JSP标签库就能够在你的Web站点上实现GoogleMaps的所有功能而且不需要javascript或AJAX编程。它还...

    JAVA上百实例源码以及开源项目

     QQ客户端登录界面,中部有三个JPanel,有一个叫选项卡窗口管理。还可以更新好友列表,响应用户双击的事件,并得到好友的编号,把聊天界面加入到管理类,设置密码保护等。 Java编写的网页版魔方游戏 内容索引:JAVA...

    JAVA上百实例源码以及开源项目源代码

    QQ客户端登录界面,中部有三个JPanel,有一个叫选项卡窗口管理。还可以更新好友列表,响应用户双击的事件,并得到好友的编号,把聊天界面加入到管理类,设置密码保护等。 Java编写的网页版魔方游戏 内容索引:JAVA...

Global site tag (gtag.js) - Google Analytics