【异步方法与事务回滚】

需求:

客户导入文件,先插入一条数据到导入记录表,然后给客户一个反馈 (导入中,请稍后查看) ,中间调用一个异步方法——执行具体的文件解析,数据存储

问题一:怎样成功调用异步方法?

方案一:另外写一个类B里面有异步方法,在类A里面注入B类,用时直接调用B的异步方法即可;

方案二:@Lazy+自己注入自己 ,用时直接本类调用,避免了另外创建一个类放异步方法。


@Slf4j
public class aaa implements AAA{

    /**
     * 为了使在同一个类中的异步方法生效 故加@Lazy注解 并且使用本类调用异步方法
     */
    @Resource
    @Lazy
    private aaa aaatService;

    /**
     * 导入excel
     *
     * @param file
     */
    @Override
    public void achieveImportExcel(MultipartFile file) {
       
        //同步方法。。。

      //调用异步方法
      aaatService.XXX();
    }



 @Async
 @Transactional(rollbackFor = Exception.class)
 public void XXX() {

    //异步方法业务代码。。。
    
}


}

问题二:异步方法抛出了异常需要回滚,回滚需要数据库插入一条记录,但是catch里面的数据库插入数据的代码也被回滚了;

解决方案:因为这个异步方法不论是try还是catch里面的数据库操作都是同一个数据库连接,最后决定catch里面的数据库操作抽取成一个异步方法,因为线程之间事务相互隔离,可以解决catch里面插入数据失败问题。

@Async
@Transactional(rollbackFor = Exception.class)
public void XXX() {

    //异步方法业务代码。。。
    try{
    //数据库操作。。。

    }catch (Exception e){
   
   //调用异步方法完成数据库操作
        aaaService.yyy();
    }
    


/**
     * 异步设置记录失败状态
     * @param record
     * @param importExcelInsertFailed
     */
    @Async
    public void yyy() {

       //数据库操作,插入一条记录

    }



}

问题三:同步方法执行完业务代码,开启子线程执行业务代码,没等创建子线程,同步方法结束了,导致异步方法还没开始就结束了。。。

解决方案:使用sleep方法,让同步方法的主线程睡一小会儿,给它一个创建子线程的时间即可。

 /**
     * 改造同步方法
     *
     * @param file
     */
    @Override
    public void achieveImportExcel(MultipartFile file) {
       
        //同步方法。。。

      //调用异步方法
      aaatService.XXX();
        
        //线程睡眠,让异步方法有时间创建子线程执行任务
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }



    }

问题四:嵌套事务回滚多了 

因为doOtherThing方法出现了异常,没有手动捕获,会继续往上抛,到外层add方法的代理方法中捕获了异常。所以,这种情况是直接回滚了整个事务,不只回滚单个保存点。

解决方案:这里引入嵌套事务的内部回滚使用方法

 可以将内部嵌套事务放在try/catch中,并且不继续往上抛异常。这样就能保证,如果内部嵌套事务中出现异常,只回滚内部事务,而不影响外部事务。

第四部分解决方案引用文章:

spring事务(注解 @Transactional )失效的12种场景_transactional不生效的场景_春天的早晨的博客-CSDN博客

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值