浅谈MyBatis中的SqlSession

SqlSession: 是MyBatis对外提供的最关键的核心接口,通过它可以执行数据库读写命令、获取映射器、管理事务等。


我们这里主要为了介绍MyBatis中的SqlSession,我们在 MyBatis binding模块分析 最后的分析中,我们虽然是通过Mapper接口进行编程的,但是其实我们最后都是通过SqlSession进行查询的。
在这里插入图片描述

我们可以看到SqlSession里面有很多的方法,我们面向Mapper接口编程,最终都是通过我们binding模块,通过分析需要执行SQL语句的类型,以及我们的返回类型等信息,来确定我们会使用哪个方法
在这里插入图片描述

这里我们来看看我们的查询方法,我们上图中虽然为查询接口划分了很多个方法,但是其实他们调用的都是同一个方法
在这里插入图片描述


如我们之前使用过的 selectOne() 方法,我们发现它就是向我们上图中的一样,调用 selectList(),然后去其中的第一个参数,然后我们跟踪 searchList() 方法,发现最后和上图一样调用了 Executor.query() 方法
在这里插入图片描述
在这里插入图片描述


虽然我们发现我们面向接口编程,最后还是会被转化为 SqlSession 查询,但是我们上述也会发现其实我们真正连接数据库,执行我们的SQL语句的也不是我们的SqlSession,而是我们的 Executor 类,这里 Executor 类在这里我们就不细说了,这里我们还是继续了解我们的SqlSession类。




我们这里再来看一看,当我们使用我们的SqlSession类时,我们是如何创建它的。


这里我们发现我们的SqlSession对象一般是从我们的SqlSessionFactory工厂类中去取得的,至于这个SqlSessionFactory类,我之前也说到,我们在 MyBatis初始化阶段 解析完成后,它就会通过一个SqlSessionFactoryBuilder 建造者类,就会创建一个 SqlsessionFactory 类,存在于程序的整个生命周期,也是单例的。
在这里插入图片描述
在这里插入图片描述

我们在 SqlSessionFactory 的实现类中 DefaultSqlSessionFactory 可以看到
在这里插入图片描述

这里面首先我们会先从Configuration类中拿到我们MyBatis初始化阶段解析MyBatis核心配置文件的 <environment> 标签中的信息,因为我们数据库的连接就是配置在 <environment> 之中的,其中还创建了我们所说的 Executor 执行器,有关Executor的内容我们下次再说,最后就会为其创建一个SqlSession
在这里插入图片描述
在这里插入图片描述

上面是我们一般最常使用的,是通过数据库数据源来获取数据库连接,然后创建SqlSession,还有一种就是直接从数据库连接中获取SqlSession,但是其本质几乎一致,另外有关MyBatis数据源我们在 MyBatis数据源模块分析 已有介绍。


其中可能就是多了一步,需要设置当前连接是否需要自动提交事务
在这里插入图片描述



最后补充一点,我们都知道SqlSession的生命周期是方法级别的,线程不安全,要保证线程独享(方法级)。所以我们在使用过程中,在同一个方法中可能是同一个,在别的方法中就是另外一个SqlSession。


即使在同一个方法中,如果我们使用到了Sqlsession,但是我们主动调用了其 Session.close() 方法,那么他们两个之间也不是一个SqlSession了。
在这里插入图片描述

但是我们MyBatis中的SqlSession的实现类,除了我们常用的DefaultSqlSession,还有一个SqlSessionManage
在这里插入图片描述

因为使用不多,这里我们简单提下,其实我们的 SqlSessionMangage 使用了动态代理,对我们获取 SqlSession 做了一些增强处理,我们 DefaultSqlSession 类每访问一次,就是创建一个新的 SqlSession ,但是 SqlSessionMangage 就不会,如下


我们在获取SqlSession时,会先去线程副本中去查找一下,有的话直接调用,没有的话才会进行创建,它是通过了ThreadLocal来保证的器其线程安全性,每个线程都会有各自的 SqlSession,通过我们一个线程也只会创建一个SqlSession,而不会像DefaultSqlSession每次都创建一个新的SqlSession。
在这里插入图片描述
在这里插入图片描述