前面的内容在源码中查看了SqlSessionFactory对象的整个构建过程,就是下面这一行代码:
SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(inputStream);
下面我们来看一下SqlSession对象的构建过程,也就是下面这一行代码:
SqlSession session = sqlSessionFactory.openSession();
首先来看我们的起点,也就是第一步:
1、SqlSession session = sqlSessionFactory.openSession();
这一步也就是从sqlSessionFactory对象中获取SqlSession对象,那么是如何获取的呢?我们来打断点,然后继续debug:
SqlSessionFactory类是个接口,前面大家都知道,这里面真正创建的对象是DefaultSqlSessionFactory对象,那么我们来进入真正实现的地方:
1、SqlSession session = sqlSessionFactory.openSession();
2、org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
在这个方法里面,真正调用的是openSessionFromDataSource方法,这个方法有三个参数,第一个是获取默认的ExecutorType,这个是什么呢?进入方法看到返回了一个属性:
这个属性的默认值是:
这是从枚举类里面获取的SIMPLE值,我们进入枚举类看一下:
这里面定义的三个常量是我们SQL执行器的三个类型,分别是简单类型,复用类型,批量类型。如果不指定,那么默认就是简单类型。这就是openSessionFromDataSource方法的第一个参数,可以看到其他两个参数默认是空,下面我们进入这个方法查看:
1、SqlSession session = sqlSessionFactory.openSession();
2、org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
3、org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
从代码逻辑可以看出,进入方法后,先拿到全局配置中的环境配置(configuration.getEnvironment()),大家知道这里面存储的就是数据库的连接属性,根据数据源的配置,开启数据库的事务,参数传入了事务等级和是否自动提交,拿到事务后,根据事务和执行器类型获取了一个执行器(Executor),执行器是非常重要的一个环节,下面看一下如何获取执行器:
1、SqlSession session = sqlSessionFactory.openSession();
2、org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
3、org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
4、org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
可以看出前面两行是空值判断,下面是根据三种类型分别创建三种不同的执行器,我们继续看,下面有个根据条件 new CachingExecutor 的地方,我们前面说过一级缓存和二级缓存,这里就是一级缓存的执行器,我们继续往下看,有这样一行代码:
executor = (Executor)interceptorChain.pluginAll(executor);
这样看代码作用不太好理解,但是从单词意思上看,调用的是一个拦截器链方法,没错,这个方法就是我们mybatis中所有的插件拦截器执行的地方,我们进入这个方法查看一下逻辑:
1、SqlSession session = sqlSessionFactory.openSession();
2、org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
3、org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
4、org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
5、org.apache.ibatis.plugin.InterceptorChain#pluginAll
这个方法就非常简单了,这里面是所有拦截器的一个for循环的执行,我们在前面写过一个插件拦截器,即使打印SQL语句输出执行时间,我们再来看一下自定义的拦截器:
这里面也有一个plugin方法,拦截器链执行的就是这个方法,传入的参数就是我们创建的执行器,我们再来看自定义的拦截器插件类上面的注解,传入的参数也有执行器的类型,
它会根据执行器的类型判断插件是否要执行,这是拦截器起作用的条件。上面就是获取执行器的过程。我们再来回到第三步,在openSessionFromDataSource方法中,获取事务和执行器对象后,就创建了一个sqlSession对象:
return new DefaultSqlSession(configuration, executor, autoCommit);
SqlSession是一个接口,这里默认创建的对象是DefaultSqlSession对象,
1、SqlSession session = sqlSessionFactory.openSession();
2、org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
3、org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
4、org.apache.ibatis.session.defaults.DefaultSqlSession#DefaultSqlSession(org.apache.ibatis.session.Configuration, org.apache.ibatis.executor.Executor, boolean)
这里只是初始化了几个属性。DefaultSqlSession类实现了SqlSession接口,我们来看下一下SqlSession接口的大致结构:
这里面定义了很多像selectOne、selectList、update等等的操作数据库的方法,这个接口继承了Closeable接口,可以使用TWR形式操作。我们再来看这个接口的默认实现,DefaultSqlSession类的大致结构:
这里面对基础的方法有很多默认的实现,这些实现其实就是用类似jdbc的方式访问数据库,调用执行器去执行statement,例如:
执行时加了很多比如缓存的判断,等等。这些session对象中默认的方法如果直接用来操作数据库并不是很友好,意义也不大。最友好的方式是自己定义mapper。
通过这个过程我们就拿到了SqlSession对象。我们再来看前面的核心概念,
现在前面四个对象的创建过程我们都了解了。
网友评论