spring项目加入jta分布式事务的实现方式: Atomikos

一、概述:

本文主要讲述如何基于Atomikos 和spring在项目中实现分布式事务管理

二、应用场景:

如果项目中的数据源来自多个数据库,同时又需要在多数据源中保证事务,此时就需要用到分布式事务处理了。

三、实验模拟需求:

比如有两个对象:用户信息、用户存款,用户信息存在数据库A、存款信息存在数据库B,若客户甲向乙转账,需要在数据库B中对甲、乙的存款信息修改,同时在数据库A中把甲、乙的备注信息最新为最近一次的操作时间。

四、实例测试环境:

• spring、hibernate3.2

• mysql5.1.51(需要版本5.0+)

• AtomikosTransactionsEssentials-3.7.0 (详细可参加它的官网:http://www.atomikos.com  )

说明:

1. 测试的数据库需要支持分布式事务,同时JDBC要支持XA连接驱动。本次测试用的mysql5.1是支持事务的,JDBC驱动版本:mysql-connector-java-5.1.7-bin.jar,包含对 XA连接的支持:com.mysql.jdbc.jdbc2.optional.MysqlXAConnection。

五、代码及配置介绍:

源代码下载:分布式事务实例演示源代码michael_jta_code.zip

1.代码的目录结构图如下:

142653_6sDO_567296.png

转账代码片段:

/**
     * 转账测试
     * @param srcId
     * @param destId
     * @param money
     * @return boolean
     */
    public boolean doTestTransfer(String srcId, String destId, float money) {

        BankAccount srcAccount = bankAccountDao.getByUserName(srcId);
        BankAccount destAccount = bankAccountDao.getByUserName(destId);
        if (srcAccount.getDeposit() < money) {
            System.out.println("warn :" + srcAccount.getUserName()
                    + " has not enough money to transfer");
            return false;
        }
        srcAccount.setDeposit(srcAccount.getDeposit() - money);
        destAccount.setDeposit(destAccount.getDeposit() + money);
        bankAccountDao.update(srcAccount);
        bankAccountDao.update(destAccount);

        Date curTime = new Date();
        UserInfo srcUser = userInfoDao.getById(srcId);
        UserInfo destUser = userInfoDao.getById(destId);

        destUser.setRemark1(curTime + "");
        destUser.setRemark2(curTime + "");
        userInfoDao.update(destUser);
        srcUser.setRemark1(curTime + "");
        if (srcAccount.getDeposit() < 18000) {
            throw new RuntimeException("michael test exception for JTA  ");
        }
        srcUser.setRemark2(curTime + "");
        userInfoDao.update(srcUser);
        System.out.println("success done:" + srcAccount.getUserName()
                + " transfer ¥" + money + " to " + destAccount.getUserName());

        return true;
    }


jta.jdbc.properties:

jdbc.SDS.class=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
jdbc.SDS.properties=URL=jdbc:mysql://localhost:3306/Test1;user=root;password=root

jdbc.SDS2.class=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
jdbc.SDS2.properties=URL=jdbc:mysql://localhost:3306/Test2;user=root;password=root

jta.properties

com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.console_file_name = tm.out
com.atomikos.icatch.log_base_name = tmlog
com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm
com.atomikos.icatch.console_log_level = INFO


六、测试验证

1. 初始化数据:

因为mysql数据库表的类型有事务和非事务之分,建表时一定要注意确保表的类型是事务控制的:InnoDB

以下两张表请分部在两个不同的数据库

CREATE TABLE tb_user_info (
	user_name varchar(20),
	real_name varchar(10),
	remark1 varchar(50),
	remark2 varchar(50)
	) ENGINE = InnoDB;
 
INSERT INTO tb_user_info (user_name,real_name,remark1,remark2) VALUES ('husband','husband','','');
INSERT INTO tb_user_info (user_name,real_name,remark1,remark2) VALUES ('wife','wife','','');
CREATE TABLE tb_account (
 id int AUTO_INCREMENT,
 user_name varchar(20),
 deposit float(10,2),
 PRIMARY KEY(id)
 ) ENGINE = InnoDB;
 
INSERT INTO tb_account (user_name,deposit) VALUES ('husband',20000.00);
INSERT INTO tb_account (user_name,deposit) VALUES ('wife',10000.00);


转载于:https://my.oschina.net/91jason/blog/542036

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值