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

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

@Transactionalpublic void create(User user){  // 如果用户已存在,则先删除  delete(user.id);  // 创建用户  int userId = insert(user);  //  更新用户信息  update(userId);}@Asyncpublic 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);}@Transactionalpublic void doCreate(User user){    // 如果用户已存在,则先删除  delete(user.id);  // 创建用户  return insert(user);}@Asyncpublic void update(Integer userId){  Icon icon = getUserIcon(userId);  // 更新用户图片  updateUserPohot(userId,icon);}

登录后复制

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

我们可以使用TransactionTemplate替换@Transactional注解

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

登录后复制

通过使用TransactionTemplate来细分事务粒度,确保在调用异步方法之前已经提交了事务。

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

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

登录后复制

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

以上就是SpringBoot异步与事务一起使用的问题怎么解决的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2625810.html

(0)
上一篇 2025年3月7日 00:45:41
下一篇 2025年3月7日 00:46:03

AD推荐 黄金广告位招租... 更多推荐

相关推荐

发表回复

登录后才能评论