支持JMS的JTA事宜使用

支持JMS的JTA事务使用

项目中使用了activemq,用mq来处理solr索引的更新和创建,由于索引经常出现一些莫名其妙的问题,后来查了很久发现是事务没有回滚的原因,数据库的事务已经回滚了,但是jms发出去的消息已经被消费掉了,索引已经更新了,但是数据库的记录没有更新。后来找到了一个比较成熟的jta事务工具,Atomikos。

 

Atomikos可以到http://www.atomikos.com/products.html#ate下载。

 

1.拷贝jta.properties到classpath中,并修改为如下内容

com.atomikos.icatch.service =  com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.no_file = true
com.atomikos.icatch.enable_logging = false
com.atomikos.icatch.console_log_level = WARN   

 

2.修改spring中数据源的设置方式,修改如下

 

	<bean id="zzGrid_main_ds" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
        <property name="uniqueResourceName">
            <value>ZZGRID_MAIN_JDBC_RESOURCE</value>
        </property>
		<property name="xaDataSourceClassName" value="xaDataSourceClassName" />
        <property name="xaProperties">
            <props>
                <prop key="user">USER</prop>
                <prop key="password">PASSWORD</prop>
                <prop key="URL">
jdbc:mysql://localhost:3306/test;user=ro
               </prop>
            </props>
        </property>		
	</bean>

 

3.JMS发送消息的时候设置事务

 

			JmsTemplate template = new JmsTemplate();
			template.setConnectionFactory((ConnectionFactory) appContext.getBean("connectionFactory"));
			template.setDefaultDestination((Destination) appContext.getBean("queueDestination"));
			template.setSessionTransacted(true);
			template.setMessageConverter(new SolrMessageConvert());
			template.convertAndSend(solrMessage);

 

这样设置之后,在数据库回滚的时候,JTA事务同时生效。

 

另外加入在一些特殊情况下,需要手动使用jta事务的方法,比如批量更新索引。

 

try{
PlatformTransactionManager jtaTransactionManager=(JtaTransactionManager) ServiceFactory.getService("txManager");
TransactionStatus status=jtaTransactionManager.getTransaction(createTransacationDefine());
	/**具体的业务逻辑代码**/				
jtaTransactionManager.commit(status);
		}catch (Exception e) {
				logger.warn(e.getMessage());
				jtaTransactionManager.rollback(status);
			}