个人理解总结:
jta分布式事务,其实与普通的spring事务配置没多大区别,最主要的是配置不同的mapper使用不同的的数据源,然后再配atomikos和spring的jta事务管理器进行管理(spring管理atomikos),使用还有就是普通的事务API不能满足需求,需要改为对应的transactionmanager,剩下的就是添加一些简单的配置即可。
代码结构:
1.导入相应的jar包
<!--常量和版本号-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<commons.beanutils>1.9.3</commons.beanutils>
<spring.version>4.3.10.RELEASE</spring.version>
<aspectj.version>1.8.6</aspectj.version>
<aspectj.weaver>1.8.6</aspectj.weaver>
<mybatis.spring.version>1.3.0</mybatis.spring.version>
<mybatis.version>3.4.5</mybatis.version>
<mysql.version>5.1.32</mysql.version>
<junit.version>4.12</junit.version>
<commons-fileupload.version>1.3.1</commons-fileupload.version>
<commons.io.version>2.2</commons.io.version>
<commons.logging.version>1.2</commons.logging.version>
<druid.version>1.0.13</druid.version>
<solr.solrj.version>5.3.1</solr.solrj.version>
<slf4j.jcl.version>1.7.25</slf4j.jcl.version>
<slf4j.version>1.7.25</slf4j.version>
<jstl.version>1.2</jstl.version>
<servlet-api.version>2.4</servlet-api.version>
<jsp-api.version>2.0</jsp-api.version>
<log4j.version>1.2.17</log4j.version>
<log4j.core.version>2.3</log4j.core.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
<dubbo.version>2.5.8</dubbo.version>
<zkclient.version>0.10</zkclient.version>
<zookeeper.version>3.4.9</zookeeper.version>
<javassist.version>3.18.1-GA</javassist.version>
<persistence.api.version>1.0.2</persistence.api.version>
<pagehelper.version>3.7.5</pagehelper.version>
<mapper.version>2.3.4</mapper.version>
<jsqlparser.version>0.9.1</jsqlparser.version>
<jackson.version>2.9.2</jackson.version>
<fastdfs.version>1.0</fastdfs.version>
<jedis.version>2.9.0</jedis.version>
<commons.pool2.version>2.5.0</commons.pool2.version>
<spring.data.redis.version>1.8.5.RELEASE</spring.data.redis.version>
<httpclient.version>4.3.1</httpclient.version>
<commons-codec.version>1.9</commons-codec.version>
<activemq.spring.version>5.15.2</activemq.spring.version>
<activemq.core.version>5.7.0</activemq.core.version>
<freemarker.version>2.3.23</freemarker.version>
<jta.version>1.1</jta.version>
<atomikos.version>4.0.6</atomikos.version>
<cglib.nodep.version>3.2.5</cglib.nodep.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>${jta.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>atomikos-util</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jta</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jdbc</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-api</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>${cglib.nodep.version}</version>
</dependency>
<!-- Jackson Json处理工具包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<!--数据连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring AOP -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- AspectJ Runtime -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- AspectJ Weaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.weaver}</version>
</dependency>
<!-- Spring Jdbc 的支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- mybatis-spring 整合 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- Apache工具组件 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>install</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<!--IDEA编译src的java文件,而目录下的xml文件并不会一起打包,需要手动指定哪些配置文件需要读取-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
2.配置文件
<!--包扫描-->
<context:component-scan base-package="cn.test.service.impl"/>
<!--使用CGLIB动态代理-->
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/>
<!-- 解析jdbc配置文件 -->
<context:property-placeholder location="classpath:resource/jdbc.properties"/>
<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean
below) 事务传播特性配置 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- the transactional semantics... -->
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"
rollback-for="java.lang.Exception"/>
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"
rollback-for="java.lang.Exception"/>
<tx:method name="insert*" propagation="REQUIRED" isolation="DEFAULT"
rollback-for="java.lang.Exception"/>
<tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT"
rollback-for="java.lang.Exception"/>
<tx:method name="modify*" propagation="REQUIRED" isolation="DEFAULT"
rollback-for="java.lang.Exception"/>
<tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT"
rollback-for="java.lang.Exception"/>
<!-- 查询方法 -->
<tx:method name="query*" read-only="true"/>
<tx:method name="select*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 声明式事务AOP配置 -->
<aop:config>
<aop:pointcut expression="execution(* cn.test.service.impl.*.*(..))" id="tranpointcut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="tranpointcut"/>
</aop:config>
<!-- 配置atomikos事务管理器 -->
<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事务管理器 spring的事务管理器-->
<bean id="txManager" 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>
<!--数据源基础配置-->
<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.url}</prop>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.pwd}</prop>
</props>
</property>
</bean>
<!--日志数据源-->
<bean id="dataSourceLog" parent="abstractXADataSource">
<property name="uniqueResourceName">
<value>dataSourceLog</value>
</property>
<property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
<property name="xaProperties">
<props>
<prop key="URL">${jdbc.log.url}</prop>
<prop key="user">${jdbc.log.username}</prop>
<prop key="password">${jdbc.log.pwd}</prop>
</props>
</property>
</bean>
<!--sqlSessionFactoryBeanOne的配置-->
<bean id="sqlSessionFactoryBeanOne" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--
MyBatis别名
MyBatis配置文件
MyBatis配置映射文件
指定数据源
-->
<property name="typeAliasesPackage" value="cn.test.model"/>
<property name="configLocation" value="classpath:mybatis/mybatis.xml"/>
<property name="mapperLocations">
<array>
<value>classpath:cn/test/mapper/*Mapper.xml</value>
</array>
</property>
<property name="dataSource" ref="dataSourceOne"/>
</bean>
<!--包扫描-->
<bean id="mapperScannerConfigurerOne" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定对应接口的包路径-->
<property name="basePackage" value="cn.test.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBeanOne"/>
</bean>
<!--sqlSessionFactoryBeanLog的配置-->
<bean id="sqlSessionFactoryBeanLog" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--
MyBatis别名
MyBatis配置文件
MyBatis配置映射文件
指定数据源
-->
<property name="typeAliasesPackage" value="cn.test.model"/>
<property name="configLocation" value="classpath:mybatis/mybatis.xml"/>
<property name="mapperLocations">
<array>
<value>classpath:cn/test/logmapper/*Mapper.xml</value>
</array>
</property>
<property name="dataSource" ref="dataSourceLog"/>
</bean>
<!--包扫描-->
<bean id="mapperScannerConfigurerLog" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定对应接口的包路径-->
<property name="basePackage" value="cn.test.logmapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBeanLog"/>
</bean>
<bean class="com.fasterxml.jackson.databind.ObjectMapper" id="objectMapper"/>
3.代码测试