MyBatis源码解析(一) Executor执行器

1,068 阅读3分钟

JDBC执行过程

  • MyBatis的底层是JDBC实现的,首先回顾JDBC的执行过程 注:新版本的JDBC提供了SPI,不需要显示的注册驱动,因此注册驱动这一步可以省略

  • 代码示例

    /** 注册数据库驱动 - 省略 **/
    // Class.forName("com.mysql.jdbc.Driver"); 
    /** 第一步: 获取连接 */
    Connection connection = DriverManager
                    .getConnection(URL, USERNAME, PASSWORD);
    /** 第二步: 预编译SQL */
    PreparedStatement statement = connection
                    .prepareStatement("select * from  user");
    /** 第三步: 执行查询 */
    ResultSet resultSet = statement.executeQuery();
    /** 第四步: 读取结果 */
    readResultSet(resultSet);
    
Statement- JDBC 执行器
  1. JDBC有三种执行器:Statement, PreparedStatement, CallableStatement
    • StatementPreparedStatementCallableStatement都是接口
    • Statement继承自WrapperPreparedStatement继承自StatementCallableStatement继承自PreparedStatement

  • 区别
    1、Statement 普通的不带参数的查询SQL,无法防止SQL注入
    2、PreparedStatement 可进行预编译,编译一次,执行多次,效率高,可防止SQL注入
    3、CallableStatement 支持带参数的SQL操作,支持调用存储过程
  • 方法
    1. addBatch: 批处理操作,将多个SQL合并在一起,最后调用executeBatch 一起发送至数据库执行
    2. setFetchSize:设置从数据库每次读取的数量单位。该举措是为了防止一次性从数据库加载数据过多,导致内存溢出。

MyBatis执行过程

执行过程概览

MyBatis的执行流程如下图(省略了加载配件文件,创建会话工厂等步骤)

上图可用以下代码来表示

// 获取构建器
SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
// 解析XML 并构造会话工厂
factory = factoryBuilder.build(ExecutorTest.class.getResourceAsStream("/mybatis-config.xml"));
// 常见SqlSession
SqlSession sqlSession = factory.openSession(true);
// 操作Mapper接口
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 获取结果
User user = userMapper.getUser(1)

SqlSession

SqlSession 是MyBatis的门面(采用门面模式设计),核心作用是为用户提供API。API包括增、删、改、查以及提交、关闭等。其自身是没有能力处理这些请求的,所以内部会包含一个唯一的执行器 Executor,所有请求都会交给执行器来处理。如下图中SqlSession接收用户“修改”请求,然后转交给Executor。

Executor 执行器

  • 概念 执行器用于连接 SqlSession与JDBC,所有与JDBC相关的操作都要通过它。图中展示了Executor在核心对象中所处位置

  • 功能 基本功能:修改,查询,缓存维护,事务管理

    1. 没有添加和删除的方法,默认此这来两个方法走的是修改操作
    2. 这里的缓存维护指一级缓存
    3. 事务管理,提交,回滚,关闭,批处理刷新

源码解析

  • 简单执行器 - SimpleExecutor 简单执行器是默认的执行器。一个Statement只执行一次,执行完毕后则进行销毁。

  • 可重用执行器 - ReuseExecutor 可重用主要指的是Statement可以重复使用。利用Map将Statement进行缓存,每次执行前判断是否存在此Statement。

    • SqlSession和ReuseExecutor
  • 批处理执行求 - BatchExecutor 将多个Statement对应的SQL语句一次传输(调用flushStatement方法)到数据库中,进行批处理操作。

SqlSession和BatchExecutor

  • 基础执行器 - BaseExecutor 主要进行缓存维护,事务管理
  • 缓存(二级缓存)执行器 - CachingExecutor 利用装饰器模式对Executor进行包装,开启缓存后,默认先从缓存中获取数据,获取不到再从数据库中取数据。

总结

Executor是Mybatis的一个核心接口,每一个SqlSession对象都会拥有一个Executor(执行器对象)