在前面三篇文章中,我们介绍了Mybatis的基本配置文件和使用方法,在本文中将深入源码,介绍SQL语句的执行流程。
还是搬出我们前面的demo,这次聚焦main方法:
1 |
|
从上面可以看到,要想执行一条sql语句的基本流程是:
- 解析配置文件,从中获取 sqlSessionFactory;
- 从 sqlSessionFactory 中获取 sqlSession;
- 从 sqlSession 中获取 mapper;
- 执行sql语句。
下面我们一步步来看。
SqlSessionFactory
从代码上来看,这个 SqlSessionFactory 是用建造者模式来完成实例化的,需要的参数是从Mybatis配置文件得到的Reader,来看一下build方法:
SqlSessionFactoryBuilder.java
1 |
|
OK,到这里已经有一个 DefaultSqlSessionFactory 了。DefaultSqlSessionFactory 实现了 SqlSessionFactory 接口,我们来看一下这个接口都有哪些方法:
1 |
|
一眼望去,全是开启 SqlSession 的方法,哦,还有一个获取配置类 Configuration 实例的方法。
接下来可以去获取 SqlSession 了。
SqlSession
在demo中,我们是这样获取sqlSession的: sessionFactory.openSession(true)
,参数true代表设置为自动提交事务,来看下源码:
DefaultSqlSessionFactory.java
1 |
|
到此,SqlSession也拿到了,还是来看一下这个接口有啥方法吧:
1 |
|
大致看一下,主要是数据库的CRUD方法,以及事务的操作。
接下来该执行sql了。
MapperProxy
在demo中,我们是这样获取我们DAO——mapper的: sqlSession.getMapper(UserMapper.class)
。要知道,我们只是写了DAO的接口文件,并没有它的实现类。
因此可以推测,是Mybatis替我们去做了这一步,进一步可以推测,这里可能存在着一个代理类。来看下源码验证下这个推测吧:
DefaultSqlSession.java
1 |
|
Configuration.java
1 |
|
MapperRegistry.java
1 |
|
MapperProxyFactory.java
1 |
|
果不其然,通过代理的方式来实现DAO层mapper接口,进而执行sql语句。下面就看看具体是怎么执行的吧。
MapperProxy.java
1 |
|
MapperMethod.java
1 |
|
看着老长,但仔细一看,具体的执行还是回到了 sqlSession。前面曾看了一下SqlSession接口里头的方法,现在既然又转回来了,那就挑一个看一下:
DefaultSqlSession.java
1 |
|
然后在 BaseExecutor
类里一路向下:
query() -> queryFromDatabase() -> doQuery()
doQuery() 方法在 BaseExecutor
的子类中实现,这里看一下 SimpleExecutor
里的实现:
SimpleExecutor.java
1 |
|
最常用的是 PreparedStatementHandler ,就来看一下它的 query() 方法:
PreparedStatementHandler.java
1 |
|
到这里,终于执行了一条sql语句了,让我们简单地回顾一下:
- 起始站:先是获得一个 mapper 的代理类(
MapperProxy
); - 甩给 MapperMethod 去执行(
mapperMethod.execute(...)
); - 甩给 sqlSession 去执行(
sqlSession.selectList(...)
); - 甩给 executor 去执行(
executor.query(...)
); - 甩给 StatementHandler 去执行(
handler.query(...)
); - 终点站:甩给PreparedStatement去执行(
ps.execute()
)。
–END–