【问题标题】:Spring AMQP/RabbitMQ and Hibernate Transaction ManangerSpring AMQP/RabbitMQ 和 Hibernate 事务管理器
【发布时间】:2012-06-28 15:42:54
【问题描述】:

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

我使用的 Hibernate Transaction manager 配置如下:

<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 注释的方法,并可能对 DB 执行 CRUD 操作。

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

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

【问题讨论】:

    标签: rabbitmq spring-transactions spring-amqp spring-orm


    【解决方案1】:

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

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

    【讨论】:

      猜你喜欢
      • 2013-06-30
      • 1970-01-01
      • 2016-12-02
      • 2012-10-16
      • 2017-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-05
      相关资源
      最近更新 更多