原文链接:
http://www.javaworld.com/javaworld/jw-01-2009/jw-01-spring-transactions.html?page=4
Page 4 of 6
不是所有的供应商都提供这么简单的支持。做为可选方案,可以使用Apache ActiveMQ做为消息中间件并在消息代理中插入存储策略,这对几乎所有的数据库都可以正常工作。一旦你了解其中的窍门,配置起来还是蛮简单的。这在本文的shared-jms-db示范工程中有过说明。应用程序代码(在这里是单元测试代码)不需要知道具体使用的模式,因为它是通过Spring配置声明来启用的。
这个例子中的单元测试代码,SynchronousMessageTriggerAndRollbackTests
验证是否所有的功能在使用同步消息接收机制时都能正常工作。testReceiveMessageUpdateDatabase方法接收两个消息并且使用它们在数据库中插入两条数据。
当这个方法退出时,测试框架会回滚这个事务,这样你可以确认消息和数据库更新都被成功回滚,如列表3所示:
列表3. 确认消息和数据库更新的回滚
@AfterTransaction
public void checkPostConditions() {
assertEquals(0, SimpleJdbcTestUtils.countRowsInTable(jdbcTemplate, "T_FOOS"));
List<String> list = getMessages();
assertEquals(2, list.size());
}
最重要的配置是ActiveMQ的持久化策略(persistence strategy),把消息系统连接到相同的业务数据源,并且Spring JmsTemplate上的标志用来接收消息。列表4展示了如何配置ActiveMQ持久化策略:
列表4. ActiveMQ持久化配置
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"
depends-on="brokerService">
<property name="brokerURL" value="vm://localhost?async=false" />
</bean>
<bean id="brokerService" class="org.apache.activemq.broker.BrokerService" init-method="start"
destroy-method="stop">
...
<property name="persistenceAdapter">
<bean class="org.apache.activemq.store.jdbc.JDBCPersistenceAdapter">
<property name="dataSource">
<bean class="com.springsource.open.jms.JmsTransactionAwareDataSourceProxy">
<property name="targetDataSource" ref="dataSource"/>
<property name="jmsTemplate" ref="jmsTemplate"/>
</bean>
</property>
<property name="createTablesOnStartup" value="true" />
</bean>
</property>
</bean>
列表5展示了用来接收消息的Spring
JmsTemplate
上的标志:
列表5. 设置JmsTemplate
事务属性
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
...
<!-- This is important... -->
<property name="sessionTransacted" value="true" />
</bean>
没有
sessionTransacted=true
,JMS会话事务API将永远不会被调用而且消息接收不能回滚。这里的重要因素是,带有特殊async=false参数的内嵌代理以及数据源的一个封装层,两者一起确保ActiveMQ使用和Spring相同的事务JDBC连接。一个共享数据库资源某些时候可以由已有的独立资源合成而来。特别是如果它们在相同的RDBMS平台里。企业级的数据库供应商都支持同义词(或当量)概念,这里一个数据模式(schema,Oracle的术语)中的表在另外的模式中被声明为同义词。通过这样的方式,该平台里被物理分割的数据可以被同一个JDBC客户端连接所操作。比如,一个基于ActiveMQ的共享资源模式在实际系统中的实现(和上面的示范不同)通常会包括为消息和业务数据创建同义词。
by iefreer