SpringBoot异步与事务一起使用的问题怎么解决

发布时间:2023-05-05 14:27:59 作者:iii
来源:亿速云 阅读:73

这篇文章主要讲解了“SpringBoot异步与事务一起使用的问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringBoot异步与事务一起使用的问题怎么解决”吧!

最近遇到的一个场景,在一个被 @Transactional 注解的方法A中中调用了一个被 @Async 注解标记的方法B,由于方法B 在执行时方法A 的事务没有提交,但是方法B在执行过程中获取不到方法A中尚未提交的数据,从而最终倒是方法B执行异常。

@Transactional
public void create(User user){
  // 如果用户已存在,则先删除
  delete(user.id);
  // 创建用户
  int userId = insert(user);
  //  更新用户信息
  update(userId);
}
@Async
public void update(Integer userId){
  Icon icon = getUserIcon(userId);
  // 更新用户图片
  updateUserPohot(userId,icon);
}

像上面的代码,我为创建用户的方法上标记了@Transactional事务注解,然后在其中调用了update()更新方法,这个方法上标记了@Async 注解。这样代码虽然看起来没有什么问题,但是实际在执行update()方法时,由于是其他线程去执行的,就会导致有可能 create()方法对应的事务还没有提交,update() 方法就无法读取到新插入的 user 记录,从而导致更新失败。

解决方案

通过调整逻辑保证事务在调用异步方法前被提交

这个问题的原因是由于 @Transactional 和 @Async 注解一起使用导致的,那么我们可以从这个方向入手,首先我们可以先确认将create()方法的事务提交后,然后再去执行异步更新方法:

public void create(User user){
  int userId = doCreate(user);
  //  更新用户信息
  update(userId);
}
@Transactional
public void doCreate(User user){
    // 如果用户已存在,则先删除
  delete(user.id);
  // 创建用户
  return insert(user);
}
@Async
public void update(Integer userId){
  Icon icon = getUserIcon(userId);
  // 更新用户图片
  updateUserPohot(userId,icon);
}

异步方法放在事务方法外调用,这样异步方法就能够读取到已经提交的事务数据了。

或者我们还可以使用TransactionTemplate来代替 @Transactional 注解:

@Autowired
TransactionTemplate transactionTemplate;
public void create(User user){
  int userId = transactionTemplate.execute(status->{
    // 如果用户已存在,则先删除
    delete(user.id);
    // 创建用户
    return insert(user);
  });
  //  更新用户信息
  update(userId);
}
@Async
public void update(Integer userId){
  Icon icon = getUserIcon(userId);
  // 更新用户图片
  updateUserPohot(userId,icon);
}

通过 TransactionTemplate细化了事务粒度,可以保证在调用异步方法前事务已经被提交。

上面的方案基本都能 解决问题,下面是从网上找到的,spring 给出的解决方案:

@Transactional
public void create(User user){
  // 如果用户已存在,则先删除
  delete(user.id);
  // 创建用户
  int userId = insert(user);
  TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
    @Override
    public void afterCommit() {
      //  更新用户信息
      update(userId);
    }
  });
}
@Async
public void update(Integer userId){
  Icon icon = getUserIcon(userId);
  // 更新用户图片
  updateUserPohot(userId,icon);
}

通过将异步方法注册为事务提交后的操作,这样Spring可以自动帮我们在事务提交后执行对应的操作。

感谢各位的阅读,以上就是“SpringBoot异步与事务一起使用的问题怎么解决”的内容了,经过本文的学习后,相信大家对SpringBoot异步与事务一起使用的问题怎么解决这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. 网红框架SpringBoot2.x之花式运行项目
  2. 怎么解决springboot jar部署时文件/图片路径问题

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

springboot

上一篇:SpringBoot怎么实现模块日志入库

下一篇:Go语言中的函数怎么使用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》