2012-06-28 99 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。