Mybatis四大组件
Executor:执行器,用来调度StatementHandler、ParameterHandler、ResultHandler等来执行对应的SQL。
StatementHandler:回顾一下JDBC操作数据库的过程,首先加载驱动创建连接,通过连接创建Statement,之后就可以使用Statement进行增删改查操作,在Mybatis中StatementHandler可以看作是对Statement的封装,用于执行数据库操作,它是四大组件的核心。
1 | // 加载驱动 |
ParameterHandler:用于对查询参数进行处理。
ResultSetHandler:用于执行SQL后对返回的数据集ResultSet的封装处理。
首先,看一下手动加载mybatis配置文件,获取SqlSession的过程:
- 加载xml配置文件
- 通过SqlSessionFactoryBuilder构建SqlSessionFactory
- 通过SqlSessionFactory获取SqlSession
1 | // mybatis的xml配置文件 |
可以看到通过SqlSessionFactoryBuilder可以构建SqlSessionFactory,然后通过SqlSessionFactory就可以获取到SqlSession进行数据库的增删改查操作了,那么就从SqlSessionFactoryBuilder入手看一下Mybatis的执行流程。
Configuration加载
我们知道mybatis是有配置文件的,那么使用mybatis的过程中,首先它一定会去加载配置文件解析各种配置。Configuration加载包括两个部分,一个是解析配置文件,另外一个是创建SqlSessionFactory,这些操作是在SqlSessionFactoryBuilder的build方法中完成的。
1 | <!-- mybatis配置文件 --> |
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder主要干了两件事情:
- 通过传入的文件流,创建了XMLConfigBuilder对象,从名字可以看出这是一个处理XML配置文件相关的类,调用了它的parse方法,解析XML配置文件,然后返回一个Configuration对象。
- XML解析结果Configuration作为参数,调用build方法创建了DefaultSqlSessionFactory,DefaultSqlSessionFactory实现了SqlSessionFactory接口,可以作为SqlSessionFactory返回,完成SqlSessionFactory的构建。
1 | public class SqlSessionFactoryBuilder { |
配置文件解析
XMLConfigBuilder
XMLConfigBuilder主要用来解析XML配置文件,在parseConfiguration方法中可以看到,对XML文件的各个节点进行了一系列的解析,这里我们先了解一下整体流程,具体的细节可以先不管。
1 | public class XMLConfigBuilder extends BaseBuilder { |
创建SqlSessionFactory
SqlSessionFactory
SqlSessionFactory是一个接口,从名字上就可以看出它和SqlSession有关,是创建SqlSession的一个工厂,里面主要包含了openSession和getConfiguration获取Configuration对象的方法。
1 | public interface SqlSessionFactory { |
DefaultSqlSessionFactory
在SqlSessionFactoryBuilder的build方法中可以知道它创建了一个DefaultSqlSessionFactory返回,DefaultSqlSessionFactory实现了SqlSessionFactory接口,它提供了两个方法创建SqlSession,分别是openSessionFromDataSource和openSessionFromConnection,它们都创建的是DefaultSqlSession。
创建DefaultSqlSession需要传入Executor作为参数,所以会先调用Configuration的newExecutor方法创建Executor,在newExecutor方法中会根据传入的ExecutorType生成对应的Executor。
所以DefaultSqlSessionFactory也主要干了两件事:
- 创建Executor执行器
- 创建DefaultSqlSession
1 | public class DefaultSqlSessionFactory implements SqlSessionFactory { |
创建Executor
SimpleExecutor: 简单执行器,默认使用的执行器就是SimpleExecutor。
ReuseExecutor: 可重用执行器。
BatchExecutor: 批量执行器,用于进行批量处理。
CachingExecutor:缓存执行器,如果开启了缓存,会返回CachingExecutor。
1 | public class Configuration { |
查询过程的执行
经过上面的步骤,拿到了一个DefaultSqlSessionFactory,接下来就可以通过DefaultSqlSessionFactory来获取SqlSession对象了,默认返回的是DefaultSqlSession,获取到SqlSession就可以对数据库进行增删改查了。
DefaultSqlSession
DefaultSqlSession中实现了SqlSession接口中的增删改查方法,以selectList查询方法为例,可以看到最终是通过执行器进行查询的,那么接下来就以SimpleExecutor为例,看一下Mybatis的查询过程。
1 | public class DefaultSqlSession implements SqlSession { |
SimpleExecutor
Mybatis默认使用的执行器是SimpleExecutor,进入SimpleExecutor的query方法查看一下执行过程,query方法实际是在其父类BaseExecutor实现的,所以先进入BaseExecutor的query方法,这里我们只需要关注queryFromDatabase方法即可,和缓存有关的先不管:
1 | public abstract class BaseExecutor implements Executor { |
SimpleExecutor的doQuery方法:
获取Configuration配置类
生成StatementHandler
- 创建Statement
- Statement参数处理
- 调用StatementHandler的query方法进行查询
1 | public class SimpleExecutor extends BaseExecutor { |
StatementHandler的生成
StatementHandler的生成是在Configuration中的newStatementHandler方法中实现的, 可以看到创建了一个RoutingStatementHandler返回。
1 | public class Configuration { |
RoutingStatementHandler的构造函数中,根据StatementType进行判断生成哪种类型的StatementHandler,一共有三种类型:
SimpleStatementHandler
PreparedStatementHandler
CallableStatementHandler
1 |
|
Statement的生成
StatementHandler的prepare方法负责生成Statement,以PreparedStatementHandler为例,看一下Statement的生成过程:
1 | public abstract class BaseStatementHandler implements StatementHandler { |
可以看到,最终通过Connection创建了PrepareStatement。
Statement参数处理
Statement生成之后,调用了parameterize方法进行参数处理,实际上是调用ParameterHandler的setParameters方法对Statement进行参数设置:
1 | public class PreparedStatementHandler extends BaseStatementHandler { |
ParameterHandler只是一个接口,它有一个子类DefaultParameterHandler:
1 | public interface ParameterHandler { |
其中TypeHandler用于实现JAVA类型和JDBC类型的转换,它会根据参数的JAVA类型和JDBC类型选择合适的TypeHandler,再通过TypeHandler进行参数设置,以此达到JAVA类型到JDBC类型的转换。
1 | <select id="getStudentById" resultMap="studentMap" parameterType="String"> |
通过#{id,javaType=String,jdbcType=VARCHAR}可知JAVA类型是String,JDBC类型是VARCHAR,因此mabatis会使用StringTypeHandler进行参数处理。
BaseTypeHandler
进入BaseTypeHandler的setParameter看下参数的设置:
1 | public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> { |
StatementHandler的查询
由SimpleExecutor的doQuery方法可知,生成StatementHandler和Statement之后,调用了StatementHandler的query方法进行最终的查询,那么再次进入到PreparedStatementHandler,看下一下查询过程的执行:
1 | public class PreparedStatementHandler extends BaseStatementHandler { |
查询结果的处理
在PreparedStatementHandler的query方法中,最后通过ResultSetHandler的handleResultSets方法对statement的查询结果进行了处理。
ResultSetHandler只是一个接口,handleResultSets()方法在它的子类DefaultResultSetHandler中实现。
1 | public interface ResultSetHandler { |
参考:
五月的仓颉:MyBatis源码分析
acm_lkl:mybatis TypeHandler详解