spring事务中的超时时间很多人都不理解

在spring中如何使用事务是一个很大的问题,其中有一个我需要在这篇文章中着重讲解一下,就是spring事务中的超时时间问题,很多同学不知道如何才能是这个超时时间生效,导致在使用过程中出现各种各样的问题。

1、使用mybatis框架来做数据库操作
代码案例如下:

@Transactional(propagation = Propagation.REQUIRED,timeout = 5)
    @Override
    public int addArea(ConsultConfigArea area) {
    
    
        int i = commonMapper.addArea(area);
        try {
    
    
            TimeUnit.SECONDS.sleep(7);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        return i;
    }

可以看到在@Transactional注解里面设置了一个timeout=5,这里的时间单位是秒。我们在程序里面休眠了7秒,我们测试一下:
保存一个“XJ77”的数据,测试代码如下:

    @Test
    public void addAreaTest() {
    
    
        AreaService bean = applicationContext.getBean(AreaService.class);
        ConsultConfigArea area = new ConsultConfigArea();
        area.setAreaCode("XJ77");
        area.setAreaName("XJ77");
        area.setState("1");
        bean.addArea(area);
    }

单元测试的日志打印如下:
从日志打印效果来看,确实是已经提交了事务的,跟我们的预期不一样,事务设置的超时时间是5s,休眠了7s但是事务还是提交了。在这里插入图片描述
数据库中的数据:
数据也成功的插入了

从这个现象来看,是不是意味着spring事务注解设置的timeout失效了呢?

为什么会这样呢?我们来读读源码
1、首先我们看看@Transactional(propagation = Propagation.REQUIRED,timeout = 5)中的timeout是如何读取的。

我们来到事务通知类TransactionInterceptor
在这里插入图片描述
开启事务
在这里插入图片描述
开启事务
在这里插入图片描述
dobegin
在dobegin中从连接池中获取到连接对象
在这里插入图片描述
在dobegin方法中把超时时间设置到一个deadline变量中
在这里插入图片描述
在这里插入图片描述
以上就是spring中把超时时间设置到了一个deadline变量中,接下来我们读读mybatis源码:
int i = commonMapper.addArea(area);执行流程

MapperProxy
在这里插入图片描述
最终执行到这里
在这里插入图片描述
进入到prepareStatement方法
在这里插入图片描述
从这里获取超时时间,我们看看transaction.getTimeout().
在这里插入图片描述
从ThreadLocal中获取连接对象,这个ThreadLocal的值是spring中的dobegin方法中设置的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
把从spring事务中配置的超时时间设置到了statement对象中
在这里插入图片描述
在这里插入图片描述
从mybatis源码来看,spring事务注解设置的超时时间,最终在mybatis里面是设置到了statement对象中了,是用jdbc对象来控制sql的执行时间的,如果执行时间超过了设置时间就会抛出异常,这个异常就会被spring事务切面捕获到最终导致事务回滚
在这里插入图片描述
其实这里休眠10s是不影响mybatis的sql执行的,sql执行就是5s,如果超过5s就会抛出异常,而这个10s是我们的业务代码不会影响mybatis的sql执行。

所以透过现象看本质,我们业务代码里面休眠10s最终事务提交了,这个是正常现象,因为sql执行没有超过5s的。
源码学习地址:
https://study.163.com/course/courseMain.htm?courseId=1211511808&share=2&shareId=480000001878470

猜你喜欢

转载自blog.csdn.net/luoyang_java/article/details/105556722