津爱改装车|来,全搞懂,原来Mybatis执行一个sql有这么多类型,绝

Executor 执行器今天分享一下 Executor 。 它在框架中是具体sql的执行器 , sqlSession(门面模式)封装通用的api , 把具体操作委派给 Executor 执行 , Executor协同BoundSql , StatementHandler , ParameterHandler 和 ResultSetHandler 完成工作 。
它使用装饰器的方式组织 Executor 对象 。 如 CachingExecutor 装饰了SimpleExecutor 提供二级缓存功能 。
可以通过插件机制扩展功能 。 Mybatisplus 就是通过插件机制扩展的功能 。
下面是更新流程 , Executor 处于流程中间蓝色部分 , 缓存执行器 , 基础执行器 , 简单执行器三个 Executor 通过责任链的方式组织起来 , 各司其职 , 一同完成执行工作 。, 可以感受到它的作用是承上启下 。
津爱改装车|来,全搞懂,原来Mybatis执行一个sql有这么多类型,绝执行器介绍
津爱改装车|来,全搞懂,原来Mybatis执行一个sql有这么多类型,绝Mybatis 一共提供了四种执行器的实现和一个模板类:

  • 基础执行器 BaseExecutor:实现Executor接口的抽象类 , 实现了框架逻辑 , 具体的逻辑委派给子类实现 。 一级缓存也是在这里实现的 。
  • 缓存执行器 CachingExecutor:实现了二级缓存 , 是jvm级别的全局缓存 。
  • 简单执行器 SimpleExecutor:继承自 BaseExecutor , 具体执行逻辑的实现 。
  • 重用执行器 ReuseExecutor:相同的 sql 只会预编译一次 。
  • 批处理执行器 BatchExecutor:批处理执行器 使用 JDBC 的batch API 执行 SQL 的批量操作 , 如insert 或者 update 。 select的逻辑和 SimpleExecutor 的实现一样 。
今天介绍 SimpleExecutor , ReuseExecutor 和 BatchExecutor 三个执行器的特定和逻辑 ,CachingExecutor 的功能是提供二级缓存 , 暂时不在这里介绍 。
SimpleExecutor简单执行器顾名思义 , 处理的逻辑比较简单直接 , 来一个 sql 预编译一个 , 处理一个 。示例代码如下:
// 创建 SimpleExecutor SimpleExecutor simpleExecutor = new SimpleExecutor(sessionFactory.getConfiguration(),jdbcTransaction);// 获取 MappedStatement final MappedStatement ms = sessionFactory.getConfiguration().getMappedStatement("example.mapper.UserMapper.getUserByID");final BoundSql boundSql = ms.getBoundSql(1);// 执行 2 次查询simpleExecutor.doQuery(ms, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, boundSql);simpleExecutor.doQuery(ms, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, boundSql);执行结果:
[DEBUG][main] o.a.i.l.j.BaseJdbcLogger.debug ==>Preparing: select * from `user` where id = ? [DEBUG][main] m.p.ThresholdInterceptor.intercept ThresholdInterceptor plugin... [DEBUG][main] o.a.i.l.j.BaseJdbcLogger.debug ==> Parameters: 1(Integer) [DEBUG][main] o.a.i.l.j.BaseJdbcLogger.debug <==Total: 1 [DEBUG][main] o.a.i.l.j.BaseJdbcLogger.debug ==>Preparing: select * from `user` where id = ? [DEBUG][main] m.p.ThresholdInterceptor.intercept ThresholdInterceptor plugin... [DEBUG][main] o.a.i.l.j.BaseJdbcLogger.debug ==> Parameters: 1(Integer) [DEBUG][main] o.a.i.l.j.BaseJdbcLogger.debug <==Total: 1 通过日志看到 , 虽然执行相同的 sql 但是每次都要执行预编译 。 这是一个需要优化的点 。
ReuseExecutorReuseExecutor 对相同 SQL 重复编译做了优化 , 相同的 sql 的 Statement 只创建一个 。