spring整合atomikos实现分布式事务

栏目: Java · 发布时间: 6年前

内容简介:Atomikos 是一个为Java平台提供增值服务的并且开源类事务管理器,主要用于处理跨数据库事务,比如某个指令在A库和B库都有写操作,业务上要求A库和B库的写操作要具有原子性,这时候就可以用到atomikos。笔者这里整合了一个spring和atomikos的demo,并且通过案例演示说明atomikos的作用。开发工具:idea数据库:mysql , oracle

前言

Atomikos 是一个为 Java 平台提供增值服务的并且开源类事务管理器,主要用于处理跨数据库事务,比如某个指令在A库和B库都有写操作,业务上要求A库和B库的写操作要具有原子性,这时候就可以用到atomikos。笔者这里整合了一个spring和atomikos的demo,并且通过案例演示说明atomikos的作用。

准备工作

开发工具:idea

数据库:mysql , oracle

正文

源码地址: github.com/qw870602/at…

演示原理:通过在两个库的写操作之间人为制造异常来观察数据库是否回滚

演示步骤:1.正常写操作,观察数据库值的变化情况

2.在写操作语句之间制造异常,观察数据库值的变化情况

项目结构

spring整合atomikos实现分布式事务

从web.xml中可以知道,容器只加载了appliactionContext.xml,剩下的配置文件除了database.properties外都是无用文件,所以大家如果要在项目中配置的话,仅需要把appliactionContext.xml中关于atomikos的部分新增到自己项目中就OK了

appliactionContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
    <!-- 引入数据源信息的properties属性文件 -->
    <context:property-placeholder location="classpath:database.properties" />
    <!-- XA方式 -->
    <!-- MYSQL数据库配置 -->
    <bean id="mysqlDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close">
        <property name="uniqueResourceName" value="dataSource1"/>
        <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
        <property name="xaProperties">
            <props>
                <prop key="URL">${mysql.qa.db.url}</prop>
                <prop key="user">${mysql.qa.db.user}</prop>
                <prop key="password">${mysql.qa.db.password}</prop>
            </props>
        </property>
        <property name="minPoolSize" value="10" />
        <property name="maxPoolSize" value="100" />
        <property name="borrowConnectionTimeout" value="30" />
        <property name="maintenanceInterval" value="60" />
    </bean>

    <!-- ORACLE数据库配置 -->
    <bean id="oracleDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" destroy-method="close">
        <property name="uniqueResourceName" value="dataSource2"/>
        <property name="xaDataSourceClassName" value="oracle.jdbc.xa.client.OracleXADataSource" />
        <property name="xaProperties">
            <props>
                <prop key="URL">${oracle.qa.db.url}</prop>
                <prop key="user">${oracle.qa.db.user}</prop>
                <prop key="password">${oracle.qa.db.password}</prop>
            </props>
        </property>
        <property name="minPoolSize" value="10" />
        <property name="maxPoolSize" value="100" />
        <property name="borrowConnectionTimeout" value="30" />
        <property name="maintenanceInterval" value="60" />
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--<property name="configLocation" value="classpath:mybatis-config-mysql.xml" />-->
        <property name="dataSource" ref="mysqlDataSource" />
        <property name="mapperLocations" >
            <list>
                <value>classpath*:/dao/*.xml</value>
            </list>
        </property>
    </bean>
    <bean id="sqlSessionFactoryOracle" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--<property name="configLocation" value="classpath:mybatis-config.xml" />-->
        <property name="dataSource" ref="oracleDataSource" />
        <property name="mapperLocations" >
            <list>
                <value>classpath*:/daodev/*.xml</value>
            </list>
        </property>
    </bean>

    <!-- MyBatis为不同的mapper注入sqlSessionFactory -->
    <bean id="mysqlTransactionTestDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
        <property name="mapperInterface" value="com.xy.dao.MysqlTransactionTestDao" />
    </bean>
    <bean id="transactionTestDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="sqlSessionFactory" ref="sqlSessionFactoryOracle" />
        <property name="mapperInterface" value="com.xy.dao.TransactionTestDao" />
    </bean>

    <!-- 分布式事务 -->
    <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
        <property name="forceShutdown" value="true"/>
    </bean>
    <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
        <property name="transactionTimeout" value="300"/>
    </bean>
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="atomikosTransactionManager"/>
        <property name="userTransaction" ref="atomikosUserTransaction"/>
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>
    <context:annotation-config/>
    <!--<!– 自动扫描controller包下的所有类,如果@Controller注入为bean –>-->
    <!--<!–事务管理层–>-->
    <context:component-scan base-package="com.xy" />

    <!-- 注册拦截器 -->
    <!--<mvc:interceptors>
        <bean class="com.springmybatis.system.interceptor.MyInterceptor" />
    </mvc:interceptors>-->
</beans>复制代码

适用JUnit4进行单元测试

package com.xy.controller;

import com.xy.daodev.TransactionTestService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class TransactionTestMain extends AbstractJUnit4SpringContextTests {
   @Autowired
 private TransactionTestService transactionTestService;
 
 /**
  * 在同一事务有多个数据源
  */
 @Test
 public void multipleDataSource2() {
  transactionTestService.updateMultipleDataSource("1","1", 100L,"1.6");
 }
}复制代码

业务实现,当前没有异常操作

@Service
public class TransactionTestServiceImpl implements TransactionTestService {
   @Autowired
 @Qualifier("mysqlTransactionTestDao")
 private MysqlTransactionTestDao mysqlTransactionTestDao;
 
 @Autowired
 @Qualifier("transactionTestDao")
 private TransactionTestDao transactionTestDao;
 
 /**
  * 在同一事务有多个数据源
  */
 @Override
 @Transactional
 public void updateMultipleDataSource(String deUserId, String inUserid, long money,String str) {
  // 账户1转出操作
  mysqlTransactionTestDao.decreaseMoney(deUserId, money);
    //Integer.parseInt(str);
  // 账户2转入操作
  transactionTestDao.increaseMoney(inUserid, money);
  
 }  

}复制代码

mysql模拟金额转出,oracle模拟金额转入

<update id="decreaseMoney" parameterType="java.util.Map">
    UPDATE fx1 SET amount=amount - #{1,jdbcType=BIGINT} WHERE id=#{0,jdbcType=VARCHAR}
</update>复制代码
<update id="increaseMoney">
    UPDATE fx1 SET amount=amount + #{1,jdbcType=BIGINT} WHERE id=#{0,jdbcType=VARCHAR}
</update>
复制代码

mysql初始金额

spring整合atomikos实现分布式事务

oracle初始金额

spring整合atomikos实现分布式事务

执行正常操作

spring整合atomikos实现分布式事务

mysql当前金额

spring整合atomikos实现分布式事务

oracle当前金额

spring整合atomikos实现分布式事务

将被屏蔽的制造异常的代码打开

public void updateMultipleDataSource(String deUserId, String inUserid, long money,String str) {
 // 账户1转出操作
 mysqlTransactionTestDao.decreaseMoney(deUserId, money);
   Integer.parseInt("skg");
 // 账户2转入操作
 transactionTestDao.increaseMoney(inUserid, money);
}  复制代码

发现 mysql 和oracle的当前金额都没有变化,说明事务回滚成功,查看日志

spring整合atomikos实现分布式事务

发现控制台打印出了异常信息,并且atomikos调用了rollback()方法,从日志也证实了回滚成功。


以上所述就是小编给大家介绍的《spring整合atomikos实现分布式事务》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Seasoned Schemer

The Seasoned Schemer

Daniel P. Friedman、Matthias Felleisen / The MIT Press / 1995-12-21 / USD 38.00

drawings by Duane Bibbyforeword and afterword by Guy L. Steele Jr.The notion that "thinking about computing is one of the most exciting things the human mind can do" sets both The Little Schemer (form......一起来看看 《The Seasoned Schemer》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具