zoukankan      html  css  js  c++  java
  • 记一次事务报错问题 Transaction synchronization is not active

    问题场景

    在一次请求的返回结果中出现了这个错误信息“Transaction synchronization is not active”,意思是“事务同步器没有激活”,看着不像是业务代码里返回的提示,猜测是spring事务框架报出来的异常没有被捕获而报的错,在代码里一通搜索之后确实没发现这个提示信息,那是什么原因引起了这个异常呢?Google之。

    出现原因

    Google一番之后,发现了这篇文章Spring的TransactionEventListener,文中提到了可能出现这个错误信息的一种情况:

    @EventListener
    public void afterRegisterSendMail(MessageEvent event) {
        // Spring 4.2 之前
        TransactionSynchronizationManager.registerSynchronization(
                new TransactionSynchronizationAdapter() {
                    @Override
                    public void afterCommit() {
                        internalSendMailNotification(event);
                    }
                });
    }
    

    上面的代码将在事务提交后执行.如果在非事务context中将抛出java.lang.IllegalStateException: Transaction synchronization is not active

    于是去代码中搜索TransactionSynchronizationManager,果然在当前请求链路中的一个service里发现了类似的代码:

    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                    @Override
                    public void afterCommit() {
                        logger.info("afterCommit_car_move_to_otherwarehouse_carIds:{}", new Gson().toJson(form.getCarIdList()));
                        for (Long wmsCarId : form.getCarIdList()) {
                            MovedCarMessage movedCarMessage = new MovedCarMessage();
                            movedCarMessage.setOldCarId(wmsCarId);
                            Message message = MessageBuilder.of(movedCarMessage).topic(carMoveToOtherWarehouseMessageTopic).build();
                            messageProducer.syncSend(message);
                        }
                    }
                });
    

    想必是执行这段代码的时候报的异常,但是上面那篇文章说了引起这个异常的原因是“在非事务context中注册同步器”,难道当前事务没有开启?我们的业务代码一般都是使用spring的注解@Transactional来开启事务,那么去看一下开启事务的代码片段。

    根本原因

    我在调用TransactionSynchronizationManager.registerSynchronization()的方法体上找到了@Transactional注解,方法代码如下,省略具体实现:

     @Transactional
        @Override
        public BizResult departingCar(CarDepartingForm form, User user) {
        ···
        }
    

    这就奇怪了,明明方法上已经添加@Transactional注解开启事务,为什么事务开启失败,带着这个疑问再次求助了Google,发现了这篇博客spring的service类调用自己方法事务无效,作者也遇到了事务无效的问题,其中总结了事务有效性相关的几点重要信息:

    1.在需要事务管理的地方加@Transactional 注解。@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。

    2.@Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。

    3.注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据。必须在配置文件中使用配置元素,才真正开启了事务行为。(spring配置文件中,开启声明式事务)

    4.通过 元素的 “proxy-target-class” 属性值来控制是基于接口的还是基于类的代理被创建。如果 “proxy-target-class” 属值被设置为 “true”,那么基于类的代理将起作用(这时需要CGLIB库cglib.jar在CLASSPATH中)。如果 “proxy-target-class” 属值被设置为 “false” 或者这个属性被省略,那么标准的JDK基于接口的代理将起作用。

    5.Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。

    6.@Transactional的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个无事务的方法调用另一个有事务的方法,事务是不会起作用的。

    特别注意第6点:同一个类中一个无事务的方法调用另一个有事务的方法,事务是不会起作用的。这一点引起了我的注意,可能我的加了注解@Transactional的departingCar方法也是被类里另一个没有开启事务的方法调用,如果真的是这样,所有一切都解释的通了。

    果然,departingCar方法被一个没加事务的接口方法调用,从而整个方法都没有事务效果:

    //此接口方法未加事务
    @Override
        public BizResult departingCarFlowFinish(CarDepartingForm form, User user) {
           
            ···
            //在此调用事务方法
            BizResult departResult = departingCar(form, user);
            ···
    
            }
    

    解决方案

    知道了引起问题的原因,解决方法也比较简单,有好几种方法都可以解决这个问题,本文列出其中两种:
    1.比较方便、暴力的一种方法就是直接在最外层接口方法中添加事务注解,也就是给本文中的departingCarFlowFinish方法加上注解即可。
    2.也可以通过代理类调用departingCar方法,代理类中包含了事务逻辑,这样也能实现事务功能。

    如果您觉得本文对你有用,不妨帮忙点个赞,或者在评论里留言交流,欢迎您持续关注我的博客^_^
  • 相关阅读:
    liquid state machine
    CMU Deep Learning 2018 by Bhiksha Raj 学习记录(20) Recitation 8: Attention
    CMU Deep Learning 2018 by Bhiksha Raj 学习记录(18) Sequence to Sequence models: Attention Models
    CMU Deep Learning 2018 by Bhiksha Raj 学习记录(19) Lecture 16: Variational Autoencoders
    CMU Deep Learning 2018 by Bhiksha Raj 学习记录(17) Recitation 7: Visualization: What does the network learn
    CMU Deep Learning 2018 by Bhiksha Raj 学习记录(16) Recitation 6: CTC
    CMU Deep Learning 2018 by Bhiksha Raj 学习记录(15) Lecture 15: Representation Learning
    CMU Deep Learning 2018 by Bhiksha Raj 学习记录(14) Lecture 14: Connectionist Temporal Classification (CTC)
    CMU Deep Learning 2018 by Bhiksha Raj 学习记录(13) Recitation 5: Recurrent Neural Networks (Introduction)
    CMU Deep Learning 2018 by Bhiksha Raj 学习记录(12) Lecture 13: Recurrent Neural Networks 3
  • 原文地址:https://www.cnblogs.com/muxuanchan/p/11357953.html
Copyright © 2011-2022 走看看