Mybatis源码解析--StatementHandler

Mybatis源码解析--StatementHandler

背景

 

概述

StatementHandler的分类

  • RoutingStatementHandler:更具不同的StatementType创建对应的StatementHandler(装饰者模式)

  • BaseStatementHandler:对公用逻辑的抽取

  • SimpleStatementHandler:用来处理Statement

  • PreparedStatementHandler:用来处理PreparedStatement

  • CallableStatementHandler:用来处理CallableStatement

StatementHandler的创建

public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    // 下面这行代码是根据插件对StatementHandler对象的增强,可以忽略掉
    // statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }

直接创建了一个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());
    }
  }

RoutingStatementHandler构造方法内根据不同的statementType创建对应的StatementHandler,下面看一个各个StatementHandler的创建过程

SimpleStatementHandler

public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}

PreparedStatementHandler

public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}

CallableStatementHandler

public CallableStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
}

上面3个StatementHandler都调用父类的构造方法

BaseStatementHandler

protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    this.configuration = mappedStatement.getConfiguration();
    this.executor = executor;
    this.mappedStatement = mappedStatement;
    this.rowBounds = rowBounds;
​
    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    this.objectFactory = configuration.getObjectFactory();
​
    if (boundSql == null) { 
      generateKeys(parameterObject);
      boundSql = mappedStatement.getBoundSql(parameterObject);
    }
​
    this.boundSql = boundSql;
​
    this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
    this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
  }

父类构造器中出现了几个重要的对象:

  • TypeHandlerRegistry:管理着Mybatis所有的类型处理器,类型处理器提供了jdbc类型与java类型的互转

  • ParameterHandler:用于给PrepareStatement对象设置参数

  • ResultSetHandler:用于处理ResultSet,解析成java对象

StatementHandler与JDBC

StatementHandler顾名思义就是对Statement的处理,而JDBC规范中提供了3种Statement,他们之间的关系如下:

  • Statement:用于执行不带参数的简单SQL语句

  • PreparedStatement:

  • CallableStatement:

上面介绍了3种Statement对象,Mybatis针对这3种Statement分别提供了3种对应的处理类对其处理,他们的处理关系如下:

JDBC这篇文章中演示过一个demo,里面使用JDBC操作数据库,会发现每个Statement对象的生命周期都要经过创建Statement、设置参数、执行、解析结果集流程。而StatementHandler是对Statement处理的封装,说明它要提供相同的功能才能实现相同的效果,通过该接口提供的API也能印证这一点。

public interface StatementHandler {
  // 创建Statement
  Statement prepare(Connection connection, Integer transactionTimeout)
      throws SQLException;
  // 设置参数
  void parameterize(Statement statement)
      throws SQLException;
  // -----各种执行操作(开始)-----
  void batch(Statement statement)
      throws SQLException;
​
  int update(Statement statement)
      throws SQLException;
​
  <E> List<E> query(Statement statement, ResultHandler resultHandler)
      throws SQLException;
​
  <E> Cursor<E> queryCursor(Statement statement)
      throws SQLException;
  // -----各种执行操作(结束)-----
  BoundSql getBoundSql();
  // 获取ParameterHandler,该对象主要是对Statement设置参数
  ParameterHandler getParameterHandler();
}

除了接口中提供的这些功能,可以看出还少了一个对结果集的处理。其实在每个StatementHandler对象的执行操作方法中,可以看到它的身影。请参考SimpleStatementHandlerPrepareStatementHandlerCallableStatementHandlerqueryqueryCursor等方法。

  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    CallableStatement cs = (CallableStatement) statement;
    cs.execute();
    List<E> resultList = resultSetHandler.handleResultSets(cs);
    resultSetHandler.handleOutputParameters(cs);
    return resultList;
  }

Mybatis组件关系图

通过上面的分析可以看出,Mybatis对Statement复杂的生命周期进行拆解,对生命周期中每个阶段的复杂逻辑使用分而治之的思想交给不同的类处理,使得每个类只关注自己分内的事。

小结

StatementHandler是对JDBC中Statement处理逻辑的封装,通过对Statement不同阶段的拆解交给不同对象处理,从而达到解耦的目的

涉及到的编程思想:对复杂的处理逻辑分而治之

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值