Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis

http://blog.csdn.net/typa01_kk/article/details/51190147

项目进行读写分离及分库分表,在一个业务中,在一个事务中处理时候将切换多个数据源,需要保证同一事务多个数据源数据的一致性。此处使用atomikos来实现:最后附源码:

1:spring3.0之后不再支持jtom[jta]了,第三方开源软件atomikos(http://www.atomikos.com/)来实现. 
2:org.springframework.transaction.jta.JotmFactoryBean类,spring-tx-2.5.6.jar中有此类,spring-tx-3.0.0.RELEASE.jar之后没有此类。
3:atomikos事务控制框架,其中看到有3种数据源,分别是,SimpleDataSourceBean,AtomikosDataSourceBean,AtomikosNonXADataSourceBean。
   a:SimpleDataSourceBean: 这个是最简单地数据源配置,需要配置XA驱动。
   b:AtomikosDataSourceBean:  分布式数据源,Atomikos实现的数据源,需要配置XA驱动,推荐此配置,可以配置连接池的信息。
   c:AtomikosNonXADataSourceBean: 非分布式数据源,该数据源配置需要普通JDBC的驱动,可以配置连接池:
4:Atomikos支持XA(全局事务)和NON-XA(非全局事务),NON-XA[nonxadatasource]效率高于XA.XA事务往往是包括多个数据源的全局事务,非XA是单个数据源的.
5:XA连接是一个JTA事务中的参与者。XA连接不支持JDBC的自动提交特性。也就是说应用程序不必在xadatasource[XA]连接上调用Java.sql.Connection.commit()或java.sql.Connection.rollback();而应用程序应该使用UserTransaction.begin(),UserTransaction.commit()和UserTransaction.rollback().

看看pom.xml依赖:

[html]  view plain  copy
 
  1.   
  2. <dependency>  
  3.     <groupId>org.springframeworkgroupId>  
  4.     <artifactId>spring-txartifactId>  
  5.     <version>4.2.5.RELEASEversion>  
  6. dependency>  
  7. <dependency>  
  8.     <groupId>javax.transactiongroupId>  
  9.     <artifactId>jtaartifactId>  
  10.     <version>1.1version>  
  11. dependency>  
  12. <dependency>  
  13.     <groupId>com.atomikosgroupId>  
  14.     <artifactId>atomikos-utilartifactId>  
  15.     <version>4.0.2version>  
  16. dependency>  
  17. <dependency>  
  18.     <groupId>com.atomikosgroupId>  
  19.     <artifactId>transactionsartifactId>  
  20.     <version>4.0.2version>  
  21. dependency>  
  22. <dependency>  
  23.     <groupId>com.atomikosgroupId>  
  24.     <artifactId>transactions-jtaartifactId>  
  25.     <version>4.0.2version>  
  26. dependency>  
  27. <dependency>  
  28.     <groupId>com.atomikosgroupId>  
  29.     <artifactId>transactions-jdbcartifactId>  
  30.     <version>4.0.2version>  
  31. dependency>  
  32. <dependency>  
  33.     <groupId>com.atomikosgroupId>  
  34.     <artifactId>transactions-apiartifactId>  
  35.     <version>4.0.2version>  
  36. dependency>  
  37. <dependency>  
  38.     <groupId>cglibgroupId>  
  39.     <artifactId>cglib-nodepartifactId>  
  40.     <version>3.2.2version>  
  41. dependency>  
1:AtomikosDataSourceBean[XA(全局事务)]数据源配置datasource-context.xml:

[html]  view plain  copy
 
  1. xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"  
  5.     xmlns:aop="http://www.springframework.org/schema/aop"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/mvc   
  7.     http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd  
  8.     http://www.springframework.org/schema/beans   
  9.     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
  10.     http://www.springframework.org/schema/context   
  11.     http://www.springframework.org/schema/context/spring-context-4.0.xsd  
  12.     http://www.springframework.org/schema/tx   
  13.     http://www.springframework.org/schema/tx/spring-tx-4.0.xsd  
  14.     http://www.springframework.org/schema/aop   
  15.     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-lazy-init="true">  
  16.     <description>配置主-从数据源信息description>  
  17.       
  18.     <bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" abstract="true">    
  19.        <property name="xaDataSourceClassName" value="${jdbc.xaDataSourceClassName}"/>    
  20.        <property name="poolSize" value="10" />    
  21.        <property name="minPoolSize" value="10"/>    
  22.        <property name="maxPoolSize" value="30"/>    
  23.        <property name="borrowConnectionTimeout" value="60"/>    
  24.        <property name="reapTimeout" value="20"/>    
  25.        <property name="maxIdleTime" value="60"/>    
  26.        <property name="maintenanceInterval" value="60"/>    
  27.        <property name="loginTimeout" value="60"/>    
  28.        <property name="testQuery" value="${validationQuery}"/>    
  29.     bean>    
  30.     <bean id="masterDataSource" parent="abstractXADataSource">    
  31.         <property name="uniqueResourceName" value="masterDB" />    
  32.         <property name="xaProperties">  
  33.             <props>  
  34.                 <prop key="driverClassName">${jdbc.driverClassName}prop>  
  35.                 <prop key="url">${master.jdbc.url}prop>  
  36.                 <prop key="password">${jdbc.password}prop>  
  37.                     
  38.                 <prop key="username">${jdbc.username}prop>     
  39.                 <prop key="initialSize">0prop>  
  40.                 <prop key="maxActive">20prop>   
  41.                 <prop key="minIdle">0prop>  
  42.                 <prop key="maxWait">60000prop>  
  43.                 <prop key="validationQuery">${validationQuery}prop>  
  44.                 <prop key="testOnBorrow">falseprop>  
  45.                 <prop key="testOnReturn">falseprop>  
  46.                 <prop key="testWhileIdle">trueprop>  
  47.                 <prop key="removeAbandoned">trueprop>  
  48.                 <prop key="removeAbandonedTimeout">1800prop>  
  49.                 <prop key="logAbandoned">trueprop>  
  50.                 <prop key="filters">mergeStatprop>  
  51.             props>  
  52.         property>  
  53.     bean>    
  54.     <bean id="slaveDataSource" parent="abstractXADataSource">    
  55.         <property name="uniqueResourceName" value="slaveDB" />    
  56.         <property name="xaProperties">  
  57.             <props>  
  58.                 <prop key="driverClassName">${jdbc.driverClassName}prop>  
  59.                 <prop key="url">${slave.jdbc.url}prop>  
  60.                 <prop key="password">${jdbc.password}prop>  
  61.                   
  62.                 <prop key="username">${jdbc.username}prop>  
  63.                 <prop key="initialSize">0prop>  
  64.                 <prop key="maxActive">20prop>  
  65.                 <prop key="minIdle">0prop>  
  66.                 <prop key="maxWait">60000prop>  
  67.                 <prop key="validationQuery">${validationQuery}prop>  
  68.                 <prop key="testOnBorrow">falseprop>  
  69.                 <prop key="testOnReturn">falseprop>  
  70.                 <prop key="testWhileIdle">trueprop>  
  71.                 <prop key="removeAbandoned">trueprop>  
  72.                 <prop key="removeAbandonedTimeout">1800prop>  
  73.                 <prop key="logAbandoned">trueprop>  
  74.                 <prop key="filters">mergeStatprop>  
  75.             props>  
  76.         property>  
  77.     bean>    
  78. beans>  
2:spring主配置文件spring-context.xml:

[html]  view plain  copy
 
  1. xml version="1.0" encoding="UTF-8"?>    
  2. <beans xmlns="http://www.springframework.org/schema/beans"    
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"    
  4.     xmlns:context="http://www.springframework.org/schema/context"    
  5.     xmlns:aop="http://www.springframework.org/schema/aop"  
  6.     xmlns:mvc="http://www.springframework.org/schema/mvc"    
  7.     xsi:schemaLocation="http://www.springframework.org/schema/beans      
  8.                         http://www.springframework.org/schema/beans/spring-beans-3.2.xsd      
  9.                         http://www.springframework.org/schema/context      
  10.                         http://www.springframework.org/schema/context/spring-context-3.2.xsd  
  11.                         http://www.springframework.org/schema/aop   
  12.                         http://www.springframework.org/schema/aop/spring-aop-3.2.xsd      
  13.                         http://www.springframework.org/schema/mvc      
  14.                         http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">    
  15.                           
  16.       
  17.     <context:component-scan base-package="com.tx" />  
  18.       
  19.         
  20.     <aop:aspectj-autoproxy />  
  21.       
  22.       
  23.     <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">   
  24.         <property name="location" value="classpath:properties/database.properties" />          
  25.     bean>    
  26.       
  27.       
  28. beans>   
3:数据源配置参数database.properties:

[html]  view plain  copy
 
  1. #mysql-Used to verify the effectiveness of the database connection   
  2. validationQuery=SELECT 1  
  3. jdbc.initialSize=5  
  4. jdbc.maxActive=20  
  5. jdbc.maxWait=60000  
  6. jdbc.poolPreparedStatements=false  
  7. jdbc.poolMaximumIdleConnections=0  
  8. jdbc.driverClassName=org.gjt.mm.mysql.Driver  
  9. jdbc.xaDataSourceClassName=com.alibaba.druid.pool.xa.DruidXADataSource  
  10. #jdbc.xaDataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource  
  11. #1.tms business.  2.The db level optimization,data concurrency,desirable.  
  12. master.jdbc.url=jdbc:mysql://your ip:3306/master?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull  
  13. slave.jdbc.url=jdbc:mysql://your ip:3306/slave?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull  
  14. jdbc.username=username  
  15. jdbc.password=password  
4:mybatis的配置mybatis-context.xml:

[html]  view plain  copy
 
  1. xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  4.     xmlns:context="http://www.springframework.org/schema/context"  
  5.     xmlns:mvc="http://www.springframework.org/schema/mvc"   
  6.     xmlns:tx="http://www.springframework.org/schema/tx"  
  7.     xmlns:aop="http://www.springframework.org/schema/aop"   
  8.     xsi:schemaLocation="http://www.springframework.org/schema/mvc   
  9.     http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd  
  10.     http://www.springframework.org/schema/beans   
  11.     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
  12.     http://www.springframework.org/schema/context   
  13.     http://www.springframework.org/schema/context/spring-context-4.0.xsd  
  14.     http://www.springframework.org/schema/tx   
  15.     http://www.springframework.org/schema/tx/spring-tx-4.0.xsd  
  16.     http://www.springframework.org/schema/aop   
  17.     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-lazy-init="true">  
  18.     <description>MyBatis的数据库持久层配置/配置主-从数据源description>  
  19.     <bean id="masterSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
  20.         <property name="configLocation" value="classpath:mybatis/mybatis-config-master.xml" />  
  21.         <property name="dataSource" ref="masterDataSource" />  
  22.     bean>  
  23.    
  24.     <bean id="slaveSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
  25.         <property name="configLocation" value="classpath:mybatis/mybatis-config-slave.xml" />  
  26.         <property name="dataSource" ref="slaveDataSource" />  
  27.     bean>  
  28. beans>  
配置mybatis-config(此代码,只为测试分布式事务,并不涉及真实的业务!!!):

mybatis-config-master.xml:

[html]  view plain  copy
 
  1. xml version="1.0" encoding="UTF-8" ?>  
  2. >  
  3. <configuration>  
  4.     <typeAliases>  
  5.         <typeAlias alias="Member"  type="com.tx.entity.Member"/>  
  6.     typeAliases>  
  7.     <mappers>  
  8.         <mapper resource="com/tx/xml/MemberMapper.xml" />  
  9.     mappers>  
  10. configuration>  
mybatis-config-slave.xml

[html]  view plain  copy
 
  1. xml version="1.0" encoding="UTF-8" ?>  
  2. >  
  3. <configuration>  
  4.     <typeAliases>  
  5.         <typeAlias alias="MemberInfo"  type="com.tx.entity.MemberInfo"/>  
  6.     typeAliases>  
  7.     <mappers>  
  8.         <mapper resource="com/tx/xml/MemberInfoMapper.xml" />  
  9.     mappers>  
  10. configuration>  
5:Mapper的管理及注入,为mybatis的dao层mapper接口注入[绑定]sqlSessionFactory:

[html]  view plain  copy
 
  1. xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  4.     xmlns:context="http://www.springframework.org/schema/context"  
  5.     xmlns:mvc="http://www.springframework.org/schema/mvc"   
  6.     xmlns:tx="http://www.springframework.org/schema/tx"  
  7.     xmlns:aop="http://www.springframework.org/schema/aop"   
  8.     xsi:schemaLocation="http://www.springframework.org/schema/mvc   
  9.     http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd  
  10.     http://www.springframework.org/schema/beans   
  11.     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
  12.     http://www.springframework.org/schema/context   
  13.     http://www.springframework.org/schema/context/spring-context-4.0.xsd  
  14.     http://www.springframework.org/schema/tx   
  15.     http://www.springframework.org/schema/tx/spring-tx-4.0.xsd  
  16.     http://www.springframework.org/schema/aop   
  17.     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-lazy-init="true">  
  18.     <description>MyBatis为不同的mapper注入sqlSessionFactorydescription>  
  19.       
  20.     <bean id="memberMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">  
  21.         <property name="sqlSessionFactory" ref="masterSqlSessionFactory" />  
  22.         <property name="mapperInterface" value="com.tx.dao.MemberMapper" />  
  23.     bean>  
  24.        
  25.     <bean id="memberInfoMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">  
  26.         <property name="sqlSessionFactory" ref="slaveSqlSessionFactory" />  
  27.         <property name="mapperInterface" value="com.tx.dao.MemberInfoMapper" />  
  28.     bean>  
  29. beans>  
6:atomikos事务配置transaction-context.xml:

[html]  view plain  copy
 
  1. xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
  4.     xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"  
  5.     xmlns:aop="http://www.springframework.org/schema/aop"  
  6.     xsi:schemaLocation="http://www.springframework.org/schema/mvc   
  7.     http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd  
  8.     http://www.springframework.org/schema/beans   
  9.     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
  10.     http://www.springframework.org/schema/context   
  11.     http://www.springframework.org/schema/context/spring-context-4.0.xsd  
  12.     http://www.springframework.org/schema/tx   
  13.     http://www.springframework.org/schema/tx/spring-tx-4.0.xsd  
  14.     http://www.springframework.org/schema/aop   
  15.     http://www.springframework.org/schema/aop/spring-aop-4.0.xsd" default-lazy-init="true">  
  16.     <description>配置事物description>  
  17.       
  18.     <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">  
  19.         <property name="forceShutdown">  
  20.             <value>truevalue>  
  21.         property>  
  22.     bean>  
  23.    
  24.     <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">  
  25.         <property name="transactionTimeout" value="300" />  
  26.     bean>  
  27.         
  28.     <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">  
  29.         <property name="transactionManager" ref="atomikosTransactionManager" />  
  30.         <property name="userTransaction" ref="atomikosUserTransaction" />  
  31.           
  32.         <property name="allowCustomIsolationLevels" value="true"/>   
  33.     bean>  
  34.   
  35.     <aop:config  proxy-target-class="true">  
  36.         <aop:advisor pointcut="(execution(* com.tx.service.*.* (..)))" advice-ref="txAdvice" />  
  37.     aop:config>  
  38.    
  39.     <tx:advice id="txAdvice" transaction-manager="springTransactionManager">  
  40.         <tx:attributes>  
  41.             <tx:method name="get*"  propagation="REQUIRED"  read-only="true" />  
  42.             <tx:method name="find*"  propagation="REQUIRED"  read-only="true" />  
  43.             <tx:method name="has*"  propagation="REQUIRED"  read-only="true" />  
  44.             <tx:method name="locate*"  propagation="REQUIRED"  read-only="true" />  
  45.             <tx:method name="register*" propagation="REQUIRED" rollback-for="java.lang.Exception" />  
  46.         tx:attributes>  
  47.     tx:advice>  
  48. beans>  
7:配置jta启动参数在src下,最后追加详细:

[html]  view plain  copy
 
  1. com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory  
  2. com.atomikos.icatch.console_file_name = /home/logs/tx/tx.out.log  
  3. com.atomikos.icatch.log_base_name = txlog  
  4. com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm  
  5. com.atomikos.icatch.console_log_level=DEBUG  
8:代码(部分不涉及代码已删除):

a:mybatis的mapper和dao接口[MemberMapper/MemberInfoMapper]:

[java]  view plain  copy
 
  1. package com.tx.dao;  
  2. import com.tx.entity.Member;  
  3. public interface MemberMapper {  
  4.     int insert(Member record);  
  5. }  
[java]  view plain  copy
 
  1. package com.tx.dao;  
  2. import com.tx.entity.MemberInfo;  
  3. public interface MemberInfoMapper {  
  4.     int insert(MemberInfo record);  
  5. }  
[html]  view plain  copy
 
  1. xml version="1.0" encoding="UTF-8" ?>  
  2. >  
  3. <mapper namespace="com.tx.dao.MemberMapper" >  
  4.   <resultMap id="BaseResultMap" type="com.tx.entity.Member" >  
  5.     <id column="id" property="id" jdbcType="INTEGER" />  
  6.     <result column="username" property="username" jdbcType="VARCHAR" />  
  7.     <result column="password" property="password" jdbcType="VARCHAR" />  
  8.     <result column="status" property="status" jdbcType="TINYINT" />  
  9.   resultMap>  
  10.   <sql id="Base_Column_List" >  
  11.     id, username, password, status  
  12.   sql>  
  13.   <insert id="insert" parameterType="com.tx.entity.Member" >  
  14.     insert into member (id, username, password,   
  15.       status)  
  16.     values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},   
  17.       #{status,jdbcType=TINYINT})  
  18.   insert>  
  19. mapper>  
[html]  view plain  copy
 
  1. xml version="1.0" encoding="UTF-8" ?>  
  2. >  
  3. <mapper namespace="com.tx.dao.MemberInfoMapper" >  
  4.   <resultMap id="BaseResultMap" type="com.tx.entity.MemberInfo" >  
  5.     <id column="id" property="id" jdbcType="INTEGER" />  
  6.     <result column="nickname" property="nickname" jdbcType="VARCHAR" />  
  7.     <result column="realname" property="realname" jdbcType="VARCHAR" />  
  8.     <result column="age" property="age" jdbcType="TINYINT" />  
  9.   resultMap>  
  10.   <sql id="Base_Column_List" >  
  11.     id, nickname, realname, age  
  12.   sql>  
  13.   <insert id="insert" parameterType="com.tx.entity.MemberInfo" >  
  14.     insert into member_info (id, nickname, realname,   
  15.       age)  
  16.     values (#{id,jdbcType=INTEGER}, #{nickname,jdbcType=VARCHAR}, #{realname,jdbcType=VARCHAR},   
  17.       #{age,jdbcType=TINYINT})  
  18.   insert>  
  19. mapper>  
b:服务层接口和实现:

[java]  view plain  copy
 
  1. package com.tx.sevice;  
  2.   
  3. import com.tx.entity.Member;  
  4. import com.tx.entity.MemberInfo;  
  5.   
  6. public interface MemberService {  
  7.     boolean registerMember(Member member, MemberInfo memberInfo);  
  8. }  
[java]  view plain  copy
 
  1. package com.tx.sevice.impl;  
  2.   
  3. import org.slf4j.Logger;  
  4. import org.slf4j.LoggerFactory;  
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.stereotype.Service;  
  7.   
  8. import com.tx.dao.MemberInfoMapper;  
  9. import com.tx.dao.MemberMapper;  
  10. import com.tx.entity.Member;  
  11. import com.tx.entity.MemberInfo;  
  12. import com.tx.sevice.MemberService;  
  13.   
  14. @Service("memberService")  
  15. public class MemberServiceImpl implements MemberService {  
  16.       
  17.     //log  
  18.     private static final Logger LOG = LoggerFactory.getLogger(MemberServiceImpl.class);  
  19.       
  20.     @Autowired  
  21.     private MemberMapper memberMapper;  
  22.     @Autowired  
  23.     private MemberInfoMapper memberInfoMapper;  
  24.   
  25.     @Override  
  26.     public boolean registerMember(Member member, MemberInfo memberInfo) {  
  27.         boolean resRegister = false;  
  28.         try {  
  29.             if(memberMapper.insert(member) != 1){  
  30.                 throw new RuntimeException("注册用户:Member表数据插入不一致.");  
  31.             }  
  32.             if(memberInfoMapper.insert(memberInfo) != 1){  
  33.                 throw new RuntimeException("注册用户:MemberInfo表数据插入不一致.");  
  34.             }  
  35.             resRegister = true;  
  36.         } catch (Exception e) {  
  37.             LOG.info("注册用户:数据库保存异常." + e.getMessage(), e);  
  38.             throw new RuntimeException("注册用户:数据库保存异常");  
  39.         }  
  40.         return resRegister;  
  41.     }  
  42.   
  43. }  
c:junit测试代码:

[java]  view plain  copy
 
  1. package com.tx.test;  
  2.   
  3. import org.junit.Test;  
  4. import org.junit.runner.RunWith;  
  5. import org.slf4j.Logger;  
  6. import org.slf4j.LoggerFactory;  
  7. import org.springframework.beans.factory.annotation.Autowired;  
  8. import org.springframework.test.context.ContextConfiguration;  
  9. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
  10.   
  11. import com.tx.entity.Member;  
  12. import com.tx.entity.MemberInfo;  
  13. import com.tx.sevice.MemberService;  
  14.   
  15. @RunWith(SpringJUnit4ClassRunner.class)  
  16. @ContextConfiguration(locations = {"classpath:spring-context.xml","classpath:datasource-context.xml",  
  17.         "classpath:mybatis-context.xml","classpath:mapper-context.xml","classpath:transaction-context.xml"})  
  18. public class JTATest {  
  19.       
  20.     //log  
  21.     private static final Logger LOG = LoggerFactory.getLogger(JTATest.class);  
  22.       
  23.     @Autowired  
  24.     private MemberService memberService;  
  25.       
  26.     @Test  
  27.     public void testRegister(){  
  28.         Member member = new Member();  
  29.         member.setId(2);  
  30.         member.setUsername("童可可");  
  31.         member.setPassword("12345678");  
  32.         member.setStatus((byte)0);  
  33.         MemberInfo memberInfo = new MemberInfo();  
  34.         memberInfo.setId(2);  
  35.         memberInfo.setAge((byte)25);  
  36.         memberInfo.setNickname("keke");  
  37.         memberInfo.setRealname("童可可");  
  38.         if(memberService.registerMember(member, memberInfo)){  
  39.             LOG.info("##用户注册成功");  
  40.         }else{  
  41.             LOG.info("##用户注册失败");  
  42.         }  
  43.     }  
  44. }  
注:通过主键重复可以测试回滚,数据没问题,正常提交不同数据库!log4j和web.xml和sql,其他代码: Spring实现数据库读写分离/spring事务配置解释

Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis_第1张图片

效果图:

执行前,master数据库:

Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis_第2张图片

执行前,slave数据库:

Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis_第3张图片
执行后,master数据库:
Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis_第4张图片
执行后,slave数据库:
Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis_第5张图片
spring-tx-2.5.6.jar和spring-tx-3.0.0.RELEASE.jar目录:

Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis_第6张图片

Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis_第7张图片

jta.properties启动参数:

[html]  view plain  copy
 
  1. # SAMPLE PROPERTIES FILE FOR THE TRANSACTION SERVICE  
  2. # THIS FILE ILLUSTRATES THE DIFFERENT SETTINGS FOR THE TRANSACTION MANAGER  
  3. # UNCOMMENT THE ASSIGNMENTS TO OVERRIDE DEFAULT VALUES;  
  4.   
  5. # Required: factory implementation class of the transaction core.  
  6. # NOTE: there is no default for this, so it MUST be specified!   
  7. #   
  8. com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory  
  9.   
  10.           
  11. # Set base name of file where messages are output   
  12. # (also known as the 'console file').  
  13. #  
  14. com.atomikos.icatch.console_file_name = tm.out  
  15.   
  16. # Size limit (in bytes) for the console file;  
  17. # negative means unlimited.  
  18. #  
  19. com.atomikos.icatch.console_file_limit=-1  
  20.   
  21. # For size-limited console files, this option  
  22. # specifies a number of rotating files to   
  23. # maintain.  
  24. #  
  25. com.atomikos.icatch.console_file_count=1  
  26.   
  27. # Set the number of log writes between checkpoints  
  28. #  
  29. com.atomikos.icatch.checkpoint_interval=500  
  30.   
  31. # Set output directory where console file and other files are to be put  
  32. # make sure this directory exists!  
  33. #  
  34. com.atomikos.icatch.output_dir = ./  
  35.   
  36. # Set directory of log files; make sure this directory exists!  
  37. #  
  38. com.atomikos.icatch.log_base_dir = ./  
  39.   
  40. # Set base name of log file  
  41. # this name will be  used as the first part of   
  42. # the system-generated log file name  
  43. #  
  44. com.atomikos.icatch.log_base_name = tmlog  
  45.   
  46. # Set the max number of active local transactions   
  47. # or -1 for unlimited.  
  48. #  
  49. com.atomikos.icatch.max_actives = 50  
  50.   
  51. # Set the default timeout (in milliseconds) for local transactions  
  52. #  
  53. com.atomikos.icatch.default_jta_timeout = 10000  
  54.   
  55. # Set the max timeout (in milliseconds) for local transactions  
  56. #  
  57. com.atomikos.icatch.max_timeout = 300000  
  58.   
  59. # The globally unique name of this transaction manager process  
  60. # override this value with a globally unique name  
  61. #  
  62. com.atomikos.icatch.tm_unique_name = tm  
  63.       
  64. # Do we want to use parallel subtransactions? JTA's default  
  65. # is NO for J2EE compatibility  
  66. #  
  67. com.atomikos.icatch.serial_jta_transactions=true  
  68.                       
  69. # If you want to do explicit resource registration then  
  70. # you need to set this value to false.  
  71. #  
  72. com.atomikos.icatch.automatic_resource_registration=true    
  73.       
  74. # Set this to WARN, INFO or DEBUG to control the granularity  
  75. # of output to the console file.  
  76. #  
  77. com.atomikos.icatch.console_log_level=INFO  
  78.       
  79. # Do you want transaction logging to be enabled or not?  
  80. # If set to false, then no logging overhead will be done  
  81. # at the risk of losing data after restart or crash.  
  82. #  
  83. com.atomikos.icatch.enable_logging=true  
  84.   
  85. # Should two-phase commit be done in (multi-)threaded mode or not?  
  86. # Set this to false if you want commits to be ordered according  
  87. # to the order in which resources are added to the transaction.  
  88. #  
  89. # NOTE: threads are reused on JDK 1.5 or higher.   
  90. # For JDK 1.4, thread reuse is enabled as soon as the   
  91. # concurrent backport is in the classpath - see   
  92. # http://mirrors.ibiblio.org/pub/mirrors/maven2/backport-util-concurrent/backport-util-concurrent/  
  93. #  
  94. com.atomikos.icatch.threaded_2pc=false  
  95.   
  96. # Should shutdown of the VM trigger shutdown of the transaction core too?  
  97. #  
  98. com.atomikos.icatch.force_shutdown_on_vm_exit=false  

分布式事务操作之Spring+JTA可参照: http://www.cnblogs.com/wangyong/p/4174326.html
Atomikos 中文说明文档:http://blog.csdn.NET/sun8288/article/details/8674016

源代码:Spring多数据源分布式事务管理


你可能感兴趣的:(spring)