Spring AMQP/RabbitMQ和Hibernate Transaction Mananger

CAL*_*101 5 rabbitmq spring-transactions spring-orm spring-amqp

我有一个使用Hibernate和PostgreSQL的Spring应用程序.它还使用Spring AMQP(RabbitMQ).

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

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"
    p:sessionFactory-ref="sessionFactory" p:dataSource-ref="dataSource" />
Run Code Online (Sandbox Code Playgroud)

我正在使用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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

小智 1

根据 Spring 消息来源,MessageListenerContainer 的 transactionManager 属性的主要目的是在侦听器调用之前接收到的消息启动事务,并在侦听器返回或抛出异常后提交或回滚事务。因此,无需将侦听器方法设置为 @Transactional,因为事务将在调用侦听器方法之前就已启动。

如果侦听器发生错误,将引发异常,数据库事务将回滚,并且不会向消息代理发送确认(jms 事务回滚)。但如果没有 XA,可能会出现重复的消息。例如,数据库事务成功提交后,与消息代理的连接重置,并且无法将 ack 发送到代理。重新连接后,代理可能会传递重复的消息。如果你承认这一点,就没有必要和XA打交道。