使用@Async异步任务提交事物不生效

Lucare 发布于 2018/07/18 14:58
阅读 1K+
收藏 1
@Override
    @Async("asyncInvoiceExecutor")
    public void printInvoiceByType(List<InvoiceLog> invoiceLogList, Integer invoiceType, BillTaxControlInfo taxControlInfo) {
        for (InvoiceLog invoiceLog : invoiceLogList) {
            InvoiceLog invoiceLogResult = null;
            if (invoiceType == 1 || invoiceType == 2) {
                invoiceLogResult = commonInvoiceService.paperInvoiceAndPrint(invoiceLog, taxControlInfo);
            } else if (invoiceType == 3) {
                invoiceLogResult = commonInvoiceService.electronicRealTimeInvoice(invoiceLog, taxControlInfo);
            }
            logger.debug("======================= invoice print end...========================="+(invoiceLogResult == null));
            if (invoiceLogResult != null) {
                invoiceLogService.updateByPrimaryKeySelective(invoiceLogResult);
//                updateInvoiceLog(invoiceLogResult);
                logger.debug("======================= update end...=========================");
            }
        }
    }

    @Transactional
    public int updateInvoiceLog(InvoiceLog invoiceLog){
        return invoiceLogMapper.updateByPrimaryKeySelective(invoiceLog);
    }

如上代码所示,@Async首先得用在不同类中,所以下放到Service中的一个方法,这个方法有耗时操作(调用外部接口打印发票),打印完结果还要更新到数据库,为了避免大事物,将方法命名为printInvoiceByType(只读)。后面调用另一个service的方法更新记录结果,可是事物根本没提交,打印结果如下:

[18 14:28:25,176 DEBUG] [asyncInvoiceExecutor-1] rest.RestUtil - =============================调用返回结果:"{\"RetMsg\":\"4001-发票数据不合法 [A632,开票人长度不正确!]\",\"RetCode\":\"4001\"}"
[18 14:28:25,181 INFO ] [asyncInvoiceExecutor-1] impl.CommonInvoiceServiceImpl - 开具发票失败!===================>:4001-发票数据不合法 [A632,开票人长度不正确!]
[18 14:28:25,182 DEBUG] [asyncInvoiceExecutor-1] impl.InvoicingServiceImpl - ======================= invoice print end...=========================false
[18 14:28:25,183 DEBUG] [asyncInvoiceExecutor-1] InvoiceLogMapper.updateByPrimaryKeySelective - ==>  Preparing: update bill_invoice_log SET invoice_status = ?, result_code = ?, result_msg = ? where invoice_id = ? 
[18 14:28:25,183 DEBUG] [asyncInvoiceExecutor-1] InvoiceLogMapper.updateByPrimaryKeySelective - ==> Parameters: 9(Integer), 4001(String), 4001-发票数据不合法 [A632,开票人长度不正确!](String), 200011(Integer)

那个update end...也没打印,不知道怎么回事。事物是通过AOP切面配置的。

Thread dump 结果如下:

"asyncInvoiceExecutor-1@10943" prio=5 tid=0x29 nid=NA waiting
  java.lang.Thread.State: WAITING
	  at sun.misc.Unsafe.park(Unsafe.java:-1)
	  at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	  at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	  at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
	  at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1074)
	  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1134)
	  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	  at java.lang.Thread.run(Thread.java:748)

这到底怎么回事,阻塞了吗,也没报错。为什么产生这种现象。

加载中
0
Lucare
Lucare

因为较忙,忘了回复,这个还是事物的配置问题,跟@Async没有关系。

解决方法:

1. 另外创建个类 ,做异步任务处理(如果是AOP配置事物,不要放到service包下)

2. 修改事物配置,让当前方法read-only=false

0
Lucare
Lucare

坐等大神指教。

0
小艺术家被占用了

"@Async首先得用在不同类中",那@Transactional呢?

0
Lucare
Lucare

出现上面的问题,是线程池把异常吞了,实际上应该报错了(就是只读事物不能更新),我当初怀疑过有异常,但是没有debug,后来一跟还真是,所以不打印那行语句。

0
yysf
yysf
updateInvoiceLog

这个是你自己在代码中调用的,所以根本就没有事务,就是普通的函数调用,所以 就像前面所说的,应该通过代理类来调用函数,所以需要放在不同的类中

Lucare
Lucare
不同类也不行,我试过了
0
j
jianhao84

从spring容器中拿到本类的实例,然后通过拿到的实例调用方法

@Autowired
ApplicationContext applicationContext;

public void test() {
    applicationContext.getBean(本类.class).updateInvoiceLog();
}
返回顶部
顶部