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事务中的超时时间很多人都不理解_第1张图片
数据库中的数据:
数据也成功的插入了
spring事务中的超时时间很多人都不理解_第2张图片

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

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

我们来到事务通知类TransactionInterceptor
spring事务中的超时时间很多人都不理解_第3张图片
开启事务
spring事务中的超时时间很多人都不理解_第4张图片
开启事务
spring事务中的超时时间很多人都不理解_第5张图片
dobegin
在dobegin中从连接池中获取到连接对象
spring事务中的超时时间很多人都不理解_第6张图片
在dobegin方法中把超时时间设置到一个deadline变量中
spring事务中的超时时间很多人都不理解_第7张图片
spring事务中的超时时间很多人都不理解_第8张图片
以上就是spring中把超时时间设置到了一个deadline变量中,接下来我们读读mybatis源码:
int i = commonMapper.addArea(area);执行流程

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

所以透过现象看本质,我们业务代码里面休眠10s最终事务提交了,这个是正常现象,因为sql执行没有超过5s的。

你可能感兴趣的:(spring源码)