Spring+JTA+Atomikos+MyBatis分布式事务管理

   我们平时的工作中用到的Spring事务管理是管理一个数据源的。但是如果对多个数据源进行事务管理该怎么办呢?我们可以用JTA和Atomikos结合Spring来实现一个分布式事务管理的功能。了解JTA可以看一下这篇文章。下面我们看怎么实现分布式事务的。

  步骤一:添加pom.xml依赖

  步骤二:准备配置文件。jdbc.properties,jta.properties

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver

jdbc.one.url=jdbc:mysql://127.0.0.1:3306/zsyy-pt-ls?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
jdbc.one.username=root
jdbc.one.password=esbmysql@ucmed.com

jdbc.two.url=jdbc:mysql://127.0.0.1:3306/zsyy-pt-test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
jdbc.two.username=root
jdbc.two.password=esbmysql@ucmed.com

jta.properties

com.atomikos.icatch.registered=true
com.atomikos.icatch.console_file_name=ls2rm.out
com.atomikos.icatch.log_base_name=base_log
com.atomikos.icatch.log_base_dir=lslog

 步骤三、配置两个数据源

<bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" abstract="true">
        <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
        <property name="poolSize" value="10"/>
        <property name="minPoolSize" value="10"/>
        <property name="maxPoolSize" value="30"/>
        <property name="borrowConnectionTimeout" value="60"/>
        <property name="reapTimeout" value="20"/>
        <property name="maxIdleTime" value="60"/>
        <property name="maintenanceInterval" value="60"/>
        <property name="testQuery">
            <value>SELECT 1</value>
        </property>
    </bean>
    <!-- 配置数据源一 -->
    <bean id="dataSourceOne" parent="abstractXADataSource">
        <property name="uniqueResourceName">
            <value>dataSourceOne</value>
        </property>
        <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
        <property name="xaProperties">
            <props>
                <prop key="URL">${jdbc.one.url}</prop>
                <prop key="user">${jdbc.one.username}</prop>
                <prop key="password">${jdbc.one.password}</prop>
            </props>
        </property>
    </bean>
    <!--配置数据源二-->
    <bean id="dataSourceTwo" parent="abstractXADataSource">
        <property name="uniqueResourceName">
            <value>dataSourceTwo</value>
        </property>
        <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
        <property name="xaProperties">
            <props>
                <prop key="URL">${jdbc.two.url}</prop>
                <prop key="user">${jdbc.two.username}</prop>
                <prop key="password">${jdbc.two.password}</prop>
                <prop key="pinGlobalTxToPhysicalConnection">true</prop>
            </props>
        </property>
    </bean>

 

步骤四、配置分布式事务

<!--配置分布式事务-->
    <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
        <property name="forceShutdown" value="false"/>
    </bean>
    <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
        <property name="transactionTimeout" value="300000"/>
    </bean>
    <!--JTA事务管理器-->
    <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager">
            <ref bean="atomikosTransactionManager"/>
        </property>
        <property name="userTransaction">
            <ref bean="atomikosUserTransaction"/>
        </property>
        <property name="allowCustomIsolationLevels" value="true"/>
    </bean>

    <aop:aspectj-autoproxy />
    <!--声明式事务-->
    <aop:config proxy-target-class="true">
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* org.hope.database.one.service.MemberServiceImpl.addMemberAndPoints(..))"/>
    </aop:config>

    <tx:advice id="txAdvice" transaction-manager="springTransactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>
        </tx:attributes>
    </tx:advice>

 

步骤五、配置mybatis

<!--mybatis的相关配置-->
    <bean id="sqlSessionFactoryOne" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSourceOne"/>
        <property name="configLocation" value="mybatis-config.xml"/>
        <property name="typeAliasesPackage" value="org.hope.database.one.model"/>
        <property name="mapperLocations">
            <list>
                <value>classpath:mapper/one/*.xml</value>
            </list>
        </property>
    </bean>
    
    <bean id="sqlSessionFactoryTwo" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSourceTwo"/>
        <property name="configLocation" value="mybatis-config.xml"/>
        <property name="typeAliasesPackage" value="org.hope.database.two.model"/>
        <property name="mapperLocations">
            <list>
                <value>classpath:mapper/two/*.xml</value>
            </list>
        </property>
    </bean>
    <!--配置mybatis映射文件自动扫描-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="org.hope.database.one"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryOne"/>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="org.hope.database.two"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryTwo"/>
    </bean>

 

步骤六、写对应的service

  dao和model这个直接看代码吧。

package org.hope.database.one.service;

import org.hope.database.one.dao.MemberMapper;
import org.hope.database.two.dao.PointMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;


@Service("memberServiceWa")
public class MemberServiceImpl implements MemberService {

    @Autowired
    private MemberMapper memberMapper;

    @Autowired
    private PointMapper pointMapper;

    public void addMemberAndPoints(String name, int point) {
            memberMapper.addMember(name);
            String str = null;
            str.equals("wge");//此处会出现异常
            pointMapper.addPoint(point);
    }
}

 

步骤七、单元测试

package org.hope.service;

import org.hope.database.one.service.MemberService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:applicationContext.xml"})
public class MemberServiceTest {

    @Autowired
    private MemberService memberServiceWa;

    @Test
    public void addMemberAndPointTest() {
        String name = "马化腾";
        int points = 50;
        memberServiceWa.addMemberAndPoints(name, points);
    }
}

 

 

 

 

 https://gitee.com/huayicompany/spring-learn/tree/master/srping-jta-atomikos

参考:

[1] 博客,http://blog.csdn.net/zeroctu/article/details/53116351

[2] 博客,http://blog.csdn.net/sun8288/article/details/8674016,Atomickos中文文档

posted @ 2017-12-11 13:34  寻找风口的猪  阅读(6695)  评论(0编辑  收藏  举报