日期:2014-05-16  浏览次数:20422 次

Spring 里JMS和DB的事务集成

?

http://www.javaworld.com/javaworld/jw-01-2009/jw-01-spring-transactions.html?page=1

http://blog.csdn.net/yanical/article/details/4545081原文拷贝

?

不过有点长,我现在都差不都忘了里面讲的内容了。注意评论,里面提到文章讲的内容有些是错误的。

Spring里,如果同时存在JMS操作和DB操作,大概也就三种方式:

1.没有使用JTA。JMS不在事务中,DB操作在事务中???

???? a,消息处理

???? b,开始数据库事务

???? c,数据库操作

???? d,数据库提交

???????? 成功:结束

???????? 失败:回到b重试

这种方式事务没有集成,靠的纯粹是我们程序的控制,如果最终数据库提交都没成功的话,可以记下log,再人工去纠正数据。例子里把数据库操作放在了更重要的位置,其实也可以倒过来,让数据库操作先完成,只好在做jms操作,看业务需求了:

???? a,开始数据库事务

???? b,数据库操作

???? c,数据库提交

???? d,消息处理

???????? 成功:结束

???????? 失败:回到d重试

我们只要把spring配置改成

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
...
<!-- This is important... -->
<property name="sessionTransacted" value="false" />
</bean>?
再加上自己程序控制就好了。

2.如果没有使用JTA,对于上面的配置如果把属性?sessionTransacted 设成true的话,就产生了第二种方式,过程:

??? a,开始jms事务

??? b,开始数据库事务

??? c,数据库和jms操作

??? d,提交数据库操作

??? e,提交jms操作

a,b的顺序不肯定,不过对程序没影响,但是d,e的顺序是确定的。在Spring里,数据库会在spring的commit方法里提交,而JMS会在afterCommit方法里提交。如果数据库失败,JMS当然也就回滚了,但是如果数据库成功而JMS失败,就产生了数据不一致,就要加上其它措施。而且这里还有一个致命缺点,就是某些情况下即使JMS失败(比如JMS服务器down了),Spring也不会抛出异常,程序外部以为一切正常,而事实上以产生了不一致问题,而且很难发现。

3.如果使用了JTA那么把属性?sessionTransacted 设成true的话,

JMS和数据库操作就在同一个事务里了,没什么好说,最安全的方式,但是效率很低。