如何解决消息消费者尝试检索尚未插入数据库的对象的问题?

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
publishhandle之间的间隔比savepublish之间的间隔快,尽管事件通过了网络!)

我想念的是什么。我在 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 代理发布事件。