Mybatis源码笔记之浅析StatementHandler

目录

  • 概述
    • 职责
    • 类图
  • 源码
    • StatementHandler对象创建
  • 总结

概述

职责

首先了解一下statementHandler职责:主要负责处理MyBatis与JDBC之间Statement的交互,通俗而言就是负责操作Statement对象与数据库之间的交互。其执行过程中主要依赖ParameterHandler和ResultSetHandler进行参数绑定和结果实体类绑定。

类图

Mybatis源码笔记之浅析StatementHandler_第1张图片

  • BaseStatementHandler:StatementHandler接口的抽象实现类,主要用于简化StatementHandler接口的实现难度,适配
    器设计模式的体现,主要有三个实现类:
  1. SimpleStatementHandler:管理Statement对象并向数据库推送不需要预编译的SQL语句;
  2. PreparedStatementHandler:管理Statement对象并向数据库推送需要预编译的SQL语句;
  3. CallableStatementHandler:管理Statement对象并调用数据库中的存储过程;
  • RoutingStatementHandler:StatementHandler接口的另一个实现类,并没有对Statement对象其实际执行作用,只是根据StatementType来创建一个代理,代理的主要对象即对应BaseStatementHandler的三种实现类。
    从源码层面理解RoutingStatementHandler:
 public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    switch (ms.getStatementType()) {
      case STATEMENT:
        delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case PREPARED:
        delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case CALLABLE:
        delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      default:
        throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
    }
  }

源码

下面主要以查询为例,debugger源码层面分析。SQL执行开始皆从SqlSession开始。

  • DefaultSqlSession
    该类中针对增删改查存在多个重载方法,以selectList为例;
@Override
  public  List selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      MappedStatement ms = configuration.getMappedStatement(statement);
      //调用Executor中的query
      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }
  • BaseExecutor
 /**
     * 查询方法,专门提供select执行的方法
     */
    @Override
    public  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
        //获取查询SQL
        BoundSql boundSql = ms.getBoundSql(parameter);
        //创建缓存的key,即作为HashMap中的key
        CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
        //执行查询
        return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
    }

此段代码块中涉及到BoundSQL对象,此处简单提一下相关概念,后期有时间专门总结一下BoundSQl.
BoundSQl对象主要是用于存储SQL语句,以及对应的参数相关对象。
继续调用BaseExcutor中的重载query方法:

 /**
     * 执行查询逻辑,
     * 首先从缓存中获取数据,缓存中有数据则进行处理存储过程;
     * 如果缓存中没有数据,则交互数据库查询数据,则将查询结果添加到缓存中
     */
    @SuppressWarnings("unchecked")
    @Override
    public  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
        ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
        if (closed) {
            throw new ExecutorException("Executor was closed.");
        }
        //如果不是嵌套查询,且动态查询语句中flushCache = true时即