一、前言
StatementHandler
封装了底层 JDBC 的 Statement
。
二、体系结构
StatementHandler:
底层接口,定义查询、更新、参数化等接口。RoutingStatementHandler:
有点类似工厂类,根据不同的 statementType 实例化相应的StatementHandler
,并在内部持有该对象的引用。BaseStatementHandler:
抽象类,实现StatementHandler
接口。SimpleStatementHandler:
对应 JDBC 的Statement
。PreparedStatementHandler:
对应 JDBC 的PreparedStatement
。CallableStatementHandler:
对应 JDBC 的CallableStatementHandler
。2.1 BaseStatementHandler
BaseStatementHandler
为抽象类,实现StatementHandler
接口。它拥有子类所需的全部变量。主要有:TypeHandlerRegistry
: 类型处理器。ResultSetHandler:
结果集处理器。ParameterHandler:
参数处理器。Executor:
执行器
可以简单把它想象为封装了以上对象的抽象类而已,主要实现了 org.apache.ibatis.executor.statement.StatementHandler#prepare()方法
,但其中的 instantiateStatement()
还是交给子类完成,并且在构造器当中如果获取主要生成器,调用主要生成器的 processBefore
方法进行主键获取。比如 Oracel 就需要这种方式获取主键。
2.2 SimpleStatementHandler
SimpleStatementHandler
是 Mybatis 最简单的 Handler,看一下 query()
接口:
和我们使用 JDBC 编程一样,调用 statement.execute(sql);
方法调用 JDBC 驱动就能获取数据库数据了。后续使用 ResultSetHandler 进行数据到对象/集合等类型的转换操作。这我们后续详解。
当然,Mybatis 默认的不是使用这个 Handler 处理 SQL 查询,而是使用 PreparedStatementHandler
,因为它存在预编译,所以执行效率更高。
2.3 PreparedStatementHandler
2.3.1 query()
PreparedStatementHandler
与 JDBC 的 PreparedStatement
,因为它存在预编译,所以相对 Statement
来说执行效率更高,但是他也有局限性,每次只能编译相同的 SQL 语句(参数可以不同)。
从上面代码来看,PreparedStatementHandler
执行更简单,直接调用 ps.execute()
即可。后续从 PreparedS
对象中获取结果集并转换相应的类型。
2.3.1 update()
下面我们了解一下 PreparedStatementHandler
的 update()
执行流程:
逻辑非常简单,主要是增加了主键的回调设置,比如我们 insert 一条语句需要获取对应的主键 ID 做后续业务的关联,这里,就是 Mybatis 帮我们回写对应的 Object 字段里。
四、生命周期
4.1 创建
每次 Executor
相关方法执行时就会新建 StatementHandler
对象,当前,这个 StatementHandler
并非抽象类 BaseStatementHandler
的子类,而是 RoutingStatementHandler
,使用代理模式 / 工厂模式 ?。在构造器时根据参数 MappedStatement#statementType
实例化不同的类型的 StatementHandler
对象。存在如下对应关系:
STATEMENT
: SimpleStatementHandlerPREPARED
: PreparedStatementHandlerCALL
: CallableStatementHandler
五、总结
以上源码并非面面具到,只贴出核心的、部分的源码给大家参考和理解,有些地方不必深究,我们只是对 Mybatis 的设计思想、部分实现细节(比如如何做 update、query) 等有一定的了解,并非逐字逐行看。
总体来说,StatementHandler
接口是 Mybatis 框架离 JDBC 原生调用实现最近的一层,它抽象了 Mybatis 底层才会使用到的接口,并非给用户直接调用的。
BaseStatementHandler
持有多个处理器对象,包含结果集处理器、参数处理器等,它们是 一条 SQL 完成执行不可缺少的一部分,每个类职责单一,便于维护和扩展。