如何解决消息消费者尝试检索尚未插入数据库的对象的问题?
How solve the problem of that a message consumer try to retrieve an object that has not yet been inserted on DB?
我正在实现 Saga。
发布 SomthingCreated
事件后,然后在另一个进程上检索 Something
。
问题是 SomthingRepository.findById(somthingCreated.id())
returns 在另一个进程上为空,因为 Something
对象还没有插入到数据库中。
@Transactional
public String createSomething(long userId, String name) {
String somethingId = somethingRepository.newSomethingId();
Something something = new Something(userId, name);
somethingRepository.save(something);
System.out.println("save:"+System.currentTimeMillis());
return somethingId;
}
SomthingCreated
事件在 save() 之后使用 Aspect
@After("execution(* com.some.something.application.*.*(..))")
public void publish() {
DomainEventPublisher.instance().commitPublishing();
System.out.println("publish:"+System.currentTimeMillis());
}
然后,消息消费者调用应用程序逻辑。
@Transactional
public String handle(SomthingCreated somthingCreated) {
System.out.println("handle:"+System.currentTimeMillis());
Something something = somethingRepository.findById(somthingCreated.id());
something.do(); //<-- NULLPointerException
}
我觉得
执行时间是这样的,
save:1643092272658
publish:1643092272852
handle:1643092272870
(publish
和handle
之间的间隔比save
和publish
之间的间隔快,尽管事件通过了网络!)
我想念的是什么。我在 Spring.
上使用 JPA 和 RabbitMQ仓库是这样的,
@Repository
public class JpaSomethingRepository implements SomethingRepository {
@PersistenceContext
private EntityManager entityManager;
@Override
public void save(Something something) {
entityManager.persist(something);
}
我该如何解决这个问题?
我可以在 handle-method 上添加 sleep-method 并且它有效但看起来很丑。
我将 entityManager.persist() 与 @Transactional 一起使用,但为什么它没有在同一事务中插入到数据库中?
提前感谢您的回答。
因为AOP的advice
应用的顺序。
我读了这个
然后,我添加了下面的代码来配置 Aspect 顺序。
@EnableAspectJAutoProxy
@EnableTransactionManagement(order = 2)
@Aspect
@Order(1)
public class EventProcessor {
...
@After("execution(* com.some.somethin.application.*.*(..))")
public void publish() {
DomainEventPublisher.instance().commitPublishing();
}
}
我申请了订单,以便先执行更多内部@transactional 代理,然后再执行EventProcessor
代理发布事件。