同一个方法,Mybatis 多次请求数据库,是否要创建多个 SqlSession 会话?

我同事最近在使用 Mybatis 时遇到了一个问题。在一个导出 Excel 需求中,每次导出的数据过大的话,执行的时间就比较长。他就在想是不是可以开启多个线程去分段处理数据。于是,他就这样做了,然而在运行过程中出现了“could not initialize proxy – no Session”异常。

这个异常,他在网上搜索了很久,都没有解决掉。这个时候,高级工程师的作用就可以体现出来了。看没看过 Mybatis 的源码,知不知道底层原理就显得非常的重要了。

至于这个问题产生的原因和解决办法,我们后面再讲,我今天先来说一个简单的面试题。同一个方法,Mybatis 多次请求数据库,是否要创建多个 SqlSession 会话?

Mybatis 其实非常的简单。我建议大家多看看它的设计源码。这个问题其实不难,想要全面回答,我们先从两个 demo 说起,再切入 Mybatis 的源码。

public void testSqlSession() throws Exception{
    System.out.println(this.xttblogMapper.findByName(""));
    System.out.println(this.xttblogMapper.findByName("涛哥"));
}

然后,我们运行一下代码。查看控制台,有一下输出。

Mybatis SqlSession 源码分析

这说明在同一个方法,Mybatis 多次请求数据库且没有事务的情况下,创建了多个 SqlSession 会话!

然后,我们在 testSqlSession 方法上加上 @Transactional 注解看看效果。

@Transactional
public void testSqlSession(){
    System.out.println(jmbRollbackRecordMapper.findByName(""));
    System.out.println(jmbRollbackRecordMapper.findByName("涛哥"));
}

运行效果截图如下:

Mybatis @Transactional 注解源码解析

这说明,在有事务的情况下,同一个方法,Mybatis 多次请求数据库,只创建了一个 SqlSession 会话!

如果有事务,并且方法内存在多个线程的情况下,代码如下:

@Transactional
public void testSqlSession(){
    new Thread(){
        @Override
        public void run() {
            System.out.println(jmbRollbackRecordMapper.findByName(""));
        }
    }.start();
    new Thread(){
        @Override
        public void run() {
            System.out.println(jmbRollbackRecordMapper.findByName("涛哥"));
        }
    }.start();
}

运行结果如下:

Mybatis 创建 SqlSession 源码解读

在有事务的情况下,同一个方法内,有多个线程 Mybatis 多次请求数据库的情况下,创建了两个 SqlSession 会话!

哎,这个时候你可以思考一下了,为什么在同一个事务下,又开启两个 SqlSession 了呢?

这就需要查看源码了,通过源码你会发现,在启用的这两个线程中,在事务管理器 TransactionSynchronizationManager 中获取 SqlSessionHolder,再从 SqlSessionHolder 中获取 SqlSession。而这两个线程的 ThreadLocal 绑定的线程不一样,所以就重新 openSession 了一个 SqlSession。

上面只是简单的代码验证,实际上你可以深入到源码中去了解 Mybatis 的精妙设计。关于源码,我后面再讲。

同一个方法,Mybatis 多次请求数据库,是否要创建多个 SqlSession 会话?

: » 同一个方法,Mybatis 多次请求数据库,是否要创建多个 SqlSession 会话?

原创文章,作者:306829225,如若转载,请注明出处:https://blog.ytso.com/252059.html

(0)
上一篇 2022年5月3日
下一篇 2022年5月4日

相关推荐

发表回复

登录后才能评论