1:引入额外的jar
<dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jdbc</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jta</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-api</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>com.atomikos</groupId> <artifactId>transactions-jms</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>com.atomikos</groupId> <artifactId>atomikos-util</artifactId> <version>4.0.6</version> </dependency> <dependency> <groupId>javax.transaction</groupId> <artifactId>jta</artifactId> <version>1.1</version> </dependency> </dependencies>
2:配制文件
#mysql index.jdbc.driverClassName=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource index.jdbc.url=jdbc:mysql://*.*.*.*:4316/k12_fee_tabindex?serverTimezone=UTC&useSSL=false&characterEncoding=UTF8 index.jdbc.username=myhuiqu index.jdbc.password=Huiqu.com@123 merch.jdbc.driverClassName=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource merch.jdbc.url=jdbc:mysql://1.1.1.1.1:4316/k12_fee?serverTimezone=UTC&useSSL=false&characterEncoding=UTF8 merch.jdbc.username=myhuiqu merch.jdbc.password=Huiqu.com@123 user.jdbc.driverClassName=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource user.jdbc.url=jdbc:mysql://1.1.1.1.1:4316/k12_fee_userclient?serverTimezone=UTC&useSSL=false&characterEncoding=UTF8 user.jdbc.username=myhuiqu user.jdbc.password=Huiqu.com@123 #active brokerURL=tcp://1.1.1.1:61616 userName=admin password=abc123
3:数据源配制
spring-index-orm.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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" default-lazy-init="false"> <context:annotation-config /> <context:property-placeholder location="classpath*:/**/*.properties" ignore-unresolvable="true" /> <context:component-scan base-package="fbs.demo"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <bean id="k12_index_dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="ds1"/> <property name="xaDataSourceClassName" value="${index.jdbc.driverClassName}"/> <property name="xaProperties"> <props> <prop key="url">${index.jdbc.url}</prop> <prop key="user">${index.jdbc.username}</prop> <prop key="password">${index.jdbc.password}</prop> </props> </property> <property name="minPoolSize" value="10" /> <property name="maxPoolSize" value="100" /> <property name="borrowConnectionTimeout" value="30" /> <property name="testQuery" value="select 1" /> <property name="maintenanceInterval" value="60" /> </bean> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager"> <bean class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <property name="forceShutdown" value="true"/> </bean> </property> <property name="userTransaction"> <bean class="com.atomikos.icatch.jta.UserTransactionImp"/> </property> </bean> <tx:annotation-driven/> <bean id="indexJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="k12_index_dataSource" /> </bean> </beans>
spring-merch-orm.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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" default-lazy-init="false"> <context:annotation-config /> <context:property-placeholder location="classpath*:/**/*.properties" ignore-unresolvable="true" /> <context:component-scan base-package="fbs.demo"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <bean id="k12_merch_dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="ds2"/> <property name="xaDataSourceClassName" value="${merch.jdbc.driverClassName}"/> <property name="xaProperties"> <props> <prop key="url">${merch.jdbc.url}</prop> <prop key="user">${merch.jdbc.username}</prop> <prop key="password">${merch.jdbc.password}</prop> </props> </property> <property name="minPoolSize" value="10" /> <property name="maxPoolSize" value="100" /> <property name="borrowConnectionTimeout" value="30" /> <property name="testQuery" value="select 1" /> <property name="maintenanceInterval" value="60" /> </bean> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager"> <bean class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <property name="forceShutdown" value="true"/> </bean> </property> <property name="userTransaction"> <bean class="com.atomikos.icatch.jta.UserTransactionImp"/> </property> </bean> <tx:annotation-driven /> <bean id="merchJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="k12_merch_dataSource" /> </bean> </beans>
spring-user-orm.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:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:c="http://www.springframework.org/schema/c" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" default-lazy-init="false"> <context:annotation-config /> <context:property-placeholder location="classpath*:/**/*.properties" ignore-unresolvable="true" /> <context:component-scan base-package="fbs.demo"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <bean id="k12_user_dataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close"> <property name="uniqueResourceName" value="ds3"/> <property name="xaDataSourceClassName" value="${user.jdbc.driverClassName}"/> <property name="xaProperties"> <props> <prop key="url">${user.jdbc.url}</prop> <prop key="user">${user.jdbc.username}</prop> <prop key="password">${user.jdbc.password}</prop> </props> </property> <property name="minPoolSize" value="10" /> <property name="maxPoolSize" value="100" /> <property name="borrowConnectionTimeout" value="30" /> <property name="testQuery" value="select 1" /> <property name="maintenanceInterval" value="60" /> </bean> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager"> <bean class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <property name="forceShutdown" value="true"/> </bean> </property> <property name="userTransaction"> <bean class="com.atomikos.icatch.jta.UserTransactionImp"/> </property> </bean> <tx:annotation-driven /> <bean id="userJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="k12_user_dataSource" /> </bean> </beans>
spring-jms.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:amq="http://activemq.apache.org/schema/core" xmlns:jms="http://www.springframework.org/schema/jms" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-4.3.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.8.0.xsd"> <context:property-placeholder location="classpath*:/**/*.properties" /> <jms:annotation-driven></jms:annotation-driven> <amq:connectionFactory id="amqConnectionFactory" brokerURL="${brokerURL}" useAsyncSend="true" /> <!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory --> <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"> <constructor-arg ref="amqConnectionFactory" /> <property name="sessionCacheSize" value="10" /> <property name="cacheConsumers" value="false"></property> <property name="cacheProducers" value="false"></property> </bean> <!-- 类型转换器 --> <bean id="messageConverter" class="org.springframework.jms.support.converter.SimpleMessageConverter" /> <!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 --> <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <property name="messageConverter" ref="messageConverter" /> <!-- 非pub/sub模型(发布/订阅),false即队列模式 ,true为发布/订阅模式 --> <property name="pubSubDomain" value="false" /> <property name="explicitQosEnabled" value="true" /> <!--发送模式,1:非持久化,2:持久化 --> <property name="deliveryMode" value="2"></property> <!--开启分布式事务 --> <property name="sessionTransacted" value="true" /> </bean> <bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <property name="messageConverter" ref="messageConverter" /> <!-- 非pub/sub模型(发布/订阅),false即队列模式 ,true为发布/订阅模式 --> <property name="pubSubDomain" value="true" /> <property name="explicitQosEnabled" value="true" /> <!--发送模式,1:非持久化,2:持久化 --> <property name="deliveryMode" value="2"></property> <!--开启分布式事务 --> <property name="sessionTransacted" value="true" /> </bean> <!-- 商户订单同步到用户 --> <bean id="abc" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg> <value>abc</value> </constructor-arg> </bean> <!-- 消息接收监听器用于异步接收消息 --> <!-- <bean id="merch2UserListener" class="k12.fee.listener.queue.Merch2UserListener"></bean> <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory" /> <property name="destination" ref="merch2UserQueue" /> <property name="messageListener" ref="merch2UserListener" /> <property name="concurrency" value="50-100" /> <property name="sessionTransacted" value="true"></property> </bean> --> </beans>
4:service层
package fbs.demo.service; import javax.annotation.Resource; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MapMessage; import javax.jms.Message; import javax.jms.Session; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jms.core.JmsTemplate; import org.springframework.jms.core.MessageCreator; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.huiqu.common.tools.utils.CodeUtil; @Service public class FbsDemo1Service { @Resource private JdbcTemplate indexJdbcTemplate; @Resource private JdbcTemplate merchJdbcTemplate; @Resource private Destination abc; @Resource private JmsTemplate jmsQueueTemplate; @Transactional public boolean add() { String id1 = CodeUtil.getUUID(); String id2 = "2121"; String sql1="INSERT INTO tabindex0 (order_num, id_number, schools_id) VALUES (?,?,?)"; String sql2="INSERT INTO k12_fee.testa (id, NAME) VALUES (?,?)"; jmsQueueTemplate.send(abc, new MessageCreator() { // 以map形式发送,以map形式接收 @Override public Message createMessage(Session session) throws JMSException { MapMessage message = null; message = session.createMapMessage(); session.createObjectMessage(); message.setString("buyer_id", "11111111111111"); return message; } }); merchJdbcTemplate.update(sql2,id2,""); indexJdbcTemplate.update(sql1, id1,"232",11); throw new RuntimeException(""); //return true; } }
做到以上几步就可以回滚了
注:tomcat启动时出错
在每一个项目中都指定atomikos的文件名称,修改jta.properties文件中的 com.atomikos.icatch.console_file_name = rm.out com.atomikos.icatch.log_base_name = rmlog.log
com.atomikos.icatch.log_base_dir = ${catalina.base}/logs 两个属性的值,保证每个项目的名称都不一样