在Spring应用程序的事务内使用Async [英] using Async inside a transaction in Spring application

查看:81
本文介绍了在Spring应用程序的事务内使用Async的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Spring应用程序,该应用程序使用 @Transactional 方法更新MySQL DB中的特定实体详细信息,并且在同一方法中,我尝试使用 @Async 调用另一个端点.code>是又一个Spring应用程序,它从MySql DB中读取相同的实体并更新Redis存储中的值.

I have a Spring application which updates particular entity details in MySQL DB using a @Transactional method, And within the same method, I am trying to call another endpoint using @Async which is one more Spring application which reads the same entity from MySql DB and updates the value in redis storage.

现在的问题是,每次我更新实体的某些值时,有时会在redis中更新它,有时却没有.

Now the problem is, every time I update some value for the entity, sometimes its updated in redis and sometimes it's not.

当我尝试调试时,我发现有时第二个应用程序从MySql读取实体时会选择旧值而不是更新值.

When I tried to debug I found that sometimes the second application when it reads the entity from MySql is picking the old value instead of updated value.

有人可以建议我如何避免这种情况,并确保第二个应用程序始终从Mysql中选择该实体的更新值?

Can anyone suggest me what can be done to avoid this and make sure that second application always picks the updated value of that entity from Mysql?

推荐答案

M.Deinum的回答很好,但是还有另一种方法可以实现,这可能会更简单,具体取决于当前应用程序的状态..

The answer from M. Deinum is good but there is still another way to achieve this which may be simpler for you case, depending on the state of your current application.

您可以简单地将对async方法的调用包装在一个事件中,该事件将在当前事务提交后处理,因此您每次都将正确地从db中读取更新的实体.

You could simply wrap the call to the async method in an event that will be processed after your current transaction commits so you will read the updated entity from the db correctly every time.

执行此操作非常简单,让我向您展示:

Is quite simple to do this, let me show you:

import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;

 @Transactional
public void doSomething() {

    // application code here

    // this code will still execute async - but only after the
    // outer transaction that surrounds this lambda is completed.
    executeAfterTransactionCommits(() -> theOtherServiceWithAsyncMethod.doIt());

    // more business logic here in the same transaction
}

private void executeAfterTransactionCommits(Runnable task) {
    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
        public void afterCommit() {
            task.run();
        }
    });
}

基本上,这里发生的是我们为当前事务回调提供一个实现,并且仅覆盖afterCommit方法-那里还有其他可能有用的方法,请检查一下.为了避免在其他部分中使用相同的样板代码,或者只是为了使方法更具可读性,请避免输入相同的样板代码,因此我在辅助方法中提取了该样板代码.

Basically what happens here is that we supply an implementation for the current transaction callback and we only override the afterCommit method - there are others methods there that might be useful, check them out. And to avoid typing the same boilerplate code if you want to use this in other parts or simply make the method more readable I extracted that in a helper method.

这篇关于在Spring应用程序的事务内使用Async的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆