首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >MyBatis源码-解读Executor的三个实现类之SimpleExecutor(简单执行器)

MyBatis源码-解读Executor的三个实现类之SimpleExecutor(简单执行器)

作者头像
小小工匠
发布2021-08-17 11:42:16
发布2021-08-17 11:42:16
9830
举报
文章被收录于专栏:小工匠聊架构小工匠聊架构

Pre

MyBatis源码-深入理解MyBatis Executor的设计思想

工程部分见 MyBatis源码- SqlSession门面模式 & selectList 源码解析

实际中,我们都是面向SqlSession编程的,不会直接调用Executor来执行业务逻辑,这里我们仅仅是为了深入了解下Executor体系架构才这么搞的,切记。


Executor 执行器


接口继承关系

这里我们重点看下Executor的 三个实现子类。

分别是:SimpleExecutor(简单执行器)、ReuseExecutor(重用执行器)、BatchExecutor(批处理执行器)。


SimpleExecutor(简单执行器)

入门小demo

代码语言:javascript
复制
package com.artisan;

import com.artisan.bean.User;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.SimpleExecutor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.transaction.jdbc.JdbcTransaction;
import org.junit.Test;

import java.sql.SQLException;
import java.util.List;

/**
 * @author 小工匠
 * @version v1.0
 * @create 2020-06-14 16:36
 * @motto show me the code ,change the word
 * @blog https://artisan.blog.csdn.net/
 * @description
 **/

public class ExecutorTest extends BaseTest {


    private MappedStatement ms;
    private JdbcTransaction jdbcTransaction;

    @Test
    public void test() throws SQLException {
        // 通过factory.openSession().getConnection()实例化JdbcTransaction ,用于构建SimpleExecutor
        jdbcTransaction = new JdbcTransaction(factory.openSession().getConnection());
        // 映射SQL
        ms = configuration.getMappedStatement("com.artisan.UserMapper.selectByid");

        // 实例化SimpleExecutor
        SimpleExecutor simpleExecutor = new SimpleExecutor(configuration, jdbcTransaction);
        // 调用doQuery执行查询
        List<User> userList = simpleExecutor.doQuery(ms, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, ms.getBoundSql(1));
        System.out.println(userList.get(0));
    }

}

有了整体的了解以后,我们拆分来看下SimpleExecutor是如何工作的


实例化SimpleExecutor

首先我们要实例化一个SimpleExecutor ,看下SimpleExecutor的源码

两个参数

代码语言:javascript
复制
  public SimpleExecutor(Configuration configuration, Transaction transaction) {
    super(configuration, transaction);
  }

使用JdbcTransaction 即可

代码语言:javascript
复制
  jdbcTransaction = new JdbcTransaction(factory.openSession().getConnection());

doQuery方法

实例化完成以后,执行方法调用doQuery

代码语言:javascript
复制
  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    .......
  }

我们可以看到这个方法是 @Override 重写父类的方法 ,去它的父类BaseExecutor看下该方法

BaseExecutor##doQuery

代码语言:javascript
复制
  protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
      throws SQLException;

抽象方法 泛型支持

我们知道MyBatis Executor 有3个子类,父类中的抽象方法doQuery其实就是让子类去重写,实现不同的功能。

SimpleExecutor 、ReuseExecutor 、BatchExecutor 都是继承 BaseExecutor, 重写doQuery来实自身的特色功能 。

参数解读

  • MappedStatement : 映射SQL
  • Object parameter : SQL中的动态参数
  • RowBounds:分页用的,默认不分页 RowBounds.DEFAULT , 可参考 org.apache.ibatis.session.RowBounds
  • ResultHandler: 自定义处理返回结果 ,不使用写 Executor.NO_RESULT_HANDLER
  • BoundSql : 绑定的SQL

入参讲完了,我们来看下doQuery方法都做了些什么工作

代码语言:javascript
复制
  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }
  1. 获取大管家 Configuration
  2. 每次都要newStatementHandler ,这个StatementHandler 后面我们重点将,是专门处理JDBC的
  3. prepareStatement --> BaseStatementHandler #prepare 方法
  4. 调用SimpleStatementHandler#query

我们看下执行过程的日志输出

代码语言:javascript
复制
17:50:42,538 DEBUG com.artisan.UserMapper.selectByid:143 - ==>  Preparing: select * from users where id = ? 
17:50:42,739 DEBUG com.artisan.UserMapper.selectByid:143 - ==> Parameters: 1(Integer)
17:50:42,808 DEBUG com.artisan.UserMapper.selectByid:143 - <==      Total: 1
User{id=1, name='artisan', age='11', sex='male', emal='123@qq.com', phoneNumber='12345', createTime=Thu Jun 04 08:00:00 CST 2020}

预编译 —执行SQL ----获取返回结果

我们加上两行代码在执行一遍

代码语言:javascript
复制
  List<User> userList2 = simpleExecutor.doQuery(ms, 1, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER, ms.getBoundSql(1));
  System.out.println(userList2.get(0));

可以发现,相同的SQL 每次调用 都会预编译 ,我们期望的结果是 相同的SQL只要编译一次即可,那SimpleExecutor不支持,那怎么办呢

Executor 的另外一个实现类 ReuseExecutor 支持该功能 。 下篇博文我们来瞅瞅ReuseExecutor

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/06/10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Pre
  • Executor 执行器
  • 接口继承关系
  • SimpleExecutor(简单执行器)
    • 入门小demo
    • 实例化SimpleExecutor
    • doQuery方法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档