2012-06-28 68 views
5

我有一个使用Hibernate和PostgreSQL的Spring应用程序。它也使用Spring AMQP(RabbitMQ)。Spring AMQP/RabbitMQ和Hibernate Transaction Mananger

我使用配置Hibernate的事务管理器如下:

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager" 
    p:sessionFactory-ref="sessionFactory" p:dataSource-ref="dataSource" /> 

我使用和SimpleMessageListenerContainer异步消息接收配置为:

@Resource(name="transactionManager") 
private PlatformTransactionManager txManager; 

@Autowired 
private MyListener messageListener; 

@Bean 
public SimpleMessageListenerContainer mySMLC() 
{ 
    final SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); 
    container.setConnectionFactory(rabbitConnectionFactory); 
    container.setQueueNames("myQueue"); 

    final MessageListenerAdapter adapter = new MessageListenerAdapter(messageListener); 
    adapter.setMessageConverter(converter); 
    container.setMessageListener(adapter); 
    container.setChannelTransacted(true); 
    container.setTransactionManager(txManager); 
    return container; 
} 

所以基本上我已经指定了接待的消息需要是事务性的。消息侦听器调用一个可以使用@Transactional注释方法的服务,并可能在数据库上执行CRUD操作。

我的问题是,使用HibernateTransactionManager来管理SimpleMessageListenerContainer级别的事务有问题吗?使用数据库事务管理器包装从RabbitMQ收到的消息是否会有问题?

我不期待XA在这里。我只想确保如果服务对数据库的任何操作都失败,则消息不会被传递给RabbitMQ代理。

回答

1

根据Spring的消息来源,MessageListenerContainer的transactionManager属性的主要用途是在侦听器调用之前接收到的消息上启动事务,并在侦听器返回或抛出异常之后提交或回滚事务。所以没有必要使侦听器方法@Transactional成为事务,因为在调用侦听器方法之前事务已经开始。

如果侦听器出现错误,将抛出异常,DB事务将回滚,并且没有确认发送给消息代理(jms事务回滚)。但是没有XA,可能会有重复的消息。例如,数据库事务成功提交后,连接消息代理重置和确认无法发送给代理。重新连接后,代理可能会传递重复的消息。如果您承认这一点,则无需处理XA。