为了简化我的问题,我
具有@Transactionnal方法的App1 createUser():
App2与RabbitMQ消息使用者
问题是,有时,App2试图在事务提交到App1之前使用RabbitMQ消息。这意味着App2无法读取数据库中的邮件数据,因为用户尚未创建。
一些解决方案可能是:
我见过春天有一个RabbitTransactionManager,但我不明白它应该如何工作。事务处理工具的内部元素似乎总是有点难以理解,而且文档也没有多大帮助。
有办法做这样的事吗?
多么?例如,如果我发送同步RabbitMQ消息而不是异步消息,还会有什么期望呢?它会阻止线程等待响应什么的吗?因为我们确实为不同的使用程序发送同步和异步消息。
发布于 2016-02-05 16:30:30
我知道这已经很晚了,但我也遇到了同样的问题,因为当时我对“交易”的理解有限。所以这对其他人来说更重要的是,你碰巧发现了这个。
当使用@Transactional将数据保存到数据库时,对数据库的保存实际上在方法返回之前不会发生,而不是在调用保存时发生。
所以如果你有一种方法
@Transactional(readOnly=false)
public void save(Object object) { //Object should be one of your entities
entityManager.persist(object); //or however you have it set up
rabbitTemplate.convertAndSend(message); //again - however yours is
}即使在将消息放入队列之前调用对象上的持久化,持久化也不会在方法返回之前实际发生,从而导致在方法返回之前和数据实际在数据库中之前将消息放到队列中。
可以在save()方法返回后嵌套@Transactional (它不是直接向前)将消息放到队列中。但是,您不能将消息放到队列中,并期望它不会被消耗。一旦它消失了。所以,如果需要的话,延迟把它放到队列中。
如果希望以同步方式从队列接收响应,请执行以下操作。在我的函数示例中--您可以这样做,但是它只会使实际持久化数据花费更长的时间,因为它将等待工作人员的响应,然后方法才能返回并实际持久化数据。(还请记住,从排队的消息接收响应是有超时的)。
因此,我的建议是不要将这两个操作放在相同的@Transactional中
发布于 2013-07-03 10:31:49
我不太熟悉@Transactionnal和spring,但在AMQP中,标准消息队列不是事务性操作,因此您必须将数据存储在db (如果db连接是事务性提交事务)中,并且只在此之后才向代理发送消息。
正确的工作流看起来像App1: createUser -> notifyUser; App2: listenForNotifications
https://stackoverflow.com/questions/17431367
复制相似问题