项目中使用了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);
}