Executor是MyBatis四大核心对象之一,是MyBatis 调度的核心,负责数据库的操作和查询缓存的维护,实际应用中涉及的SqlSession接口的功能都是基于Executor调度StatementHandler、ParameterHandler、ResultSetHandler实现的。
1.Executor继承体系
Executor继承体系如上图所示,位于继承体系最顶层的是 Executor 执行器接口,它有两个实现类,分别是BaseExecutor和 CachingExecutor。
BaseExecutor 是一个抽象类,这种通过抽象的实现接口的方式是适配器设计模式之接口适配 的体现,是Executor 的默认实现,实现了大部分 Executor 接口定义的功能,降低了接口实现的难度。BaseExecutor 的子类有三个,分别是 SimpleExecutor、ReuseExecutor 和 BatchExecutor。
SimpleExecutor : 简单执行器,是 MyBatis 中默认使用的执行器,每执行一次 update 或 select,就开启一个Statement 对象,用完就直接关闭 Statement 对象(可以是 Statement 或者是 PreparedStatment 对象)
ReuseExecutor : 可重用执行器,这里的重用指的是重复使用 Statement,它会在内部使用一个 Map 把创建的Statement 都缓存起来,每次执行 SQL 命令的时候,都会去判断是否存在基于该 SQL 的 Statement 对象,如果存在 Statement 对象并且对应的 connection 还没有关闭的情况下就继续使用之前的 Statement 对象,并将其缓存起来。因为每一个 SqlSession 都有一个新的 Executor 对象,所以我们缓存在 ReuseExecutor 上的 Statement作用域是同一个 SqlSession。
BatchExecutor : 批处理执行器,用于将多个 SQL 一次性输出到数据库
CachingExecutor: 缓存执行器,先从缓存中查询结果,如果存在就返回之前的结果;如果不存在,再委托给Executor delegate 去数据库中取,delegate 可以是上面任何一个执行器。
2.Executor 的创建和选择
我们上面提到 Executor 是由 Configuration 创建的,Configuration 会根据执行器的类型创建,如下
这一步就是执行器的创建过程,根据传入的 ExecutorType 类型来判断是哪种执行器,如果不指定 ExecutorType ,默认创建的是简单执行器。它的赋值可以通过两个地方进行赋值:
可以通过<settings>标签来设置当前工程中所有的 SqlSession 对象使用默认的 Executor
另外一种直接通过Java对方法赋值的方式
SqlSession sqlSession = factory.openSession(ExecutorType.SIMPLE);
3.Executor 的具体执行过程
我们以 SqlSesion的selectList 为例,它会调用到 executor.query 方法。
当有一个查询请求访问的时候,首先会经过 Executor 的实现类 CachingExecutor,先从缓存中查询 SQL 是否是第一次执行,如果是第一次执行的话,那么就直接执行 SQL 语句,并创建缓存,如果第二次访问相同的 SQL 语句的话,那么就会直接从缓存中提取。
上面这段代码是从 selectList -> 从缓存中 query 的具体过程,如果二级缓存为空,则由委托的Executor进行查询。
Executor采用模板方法设计模式,最终的执行是由BaseExecutor的子类的doQuery方法进行执行,到这里Executor所做的工作就完事了,后面交给StatementHandler继续执行。后面《mybatis深度历险》洗了的文章会介绍StatementHandler。
网友评论