当前位置: 移动技术网 > IT编程>开发语言>Java > mybatis StatementHandler

mybatis StatementHandler

2020年07月28日  | 移动技术网IT编程  | 我要评论

是四大神器中最重要的一个对象。
主要负责:Statement,PrepareStatement,CallableStatement创建工作。
同时负责:PrepareStatement,CallableStatement输送Sql的语句的占位符,使用ParameterHandler进行参数配置。
操作对象的运行行为update,select等。

public interface StatementHandler {
  //创建Statement,PrepareStatement,CallableStatement
  Statement prepare(Connection connection, Integer transactionTimeout)
      throws SQLException;
  //参数初始化,针对PrepareStatement,CallableStatement关联预编译Sql语句中占位符进行修改
  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 getParameterHandler();

}

StatementHandler继承关系

在这里插入图片描述

  • BaseStatementHandler
    负责实现prepare方法
  • RoutingStatementHandler
    三种Handler使用的调度器
  • SimpleStatementHandler
    Statement对象初始化
  • PreparedStatementHandler
    预编译对象PreparedStatement进行初始化
  • CallableStatementHandler
    CallableStatement

StatementHandler核心方法

StatementHandler对象是在SqlSession对象接收到操作命令时,由Configuraion中newStatementHandler方法负责调用.

public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    //RoutingStatementHandler,三种Handler使用的调度器。
    //根据传入的SQL语句返回SimpleStatementHandler,PreparedStatementHandler,CallableStatementHandler
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }

RoutingStatementHandler调度器代码,根据MappedStatement返回某种类型的StatementHandler。
怎么判断返回那种类型的Handler:取决于sql语句,没有占位符就是SimpleStatementHandler。有占位符的出现PreparedStatementHandler。call {} CallableStatementHandler。非人为控制

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());
    }

  }

返回某种类型的StatementHandler,构造方法中都调用了父类的构造方法

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) { // issue #435, get the key before calculating the statement
      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);
  }

通过以上的调用便生成了相应的Handler,后续Statement的创建工作便会在相应的handler中完成。(在BaseStatementHandler中prepare方法中调用了instantiateStatement抽象方法,该方法由子类实现。)
prepare方法实在执行器中调用的

@Override
  public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
    ErrorContext.instance().sql(boundSql.getSql());
    Statement statement = null;
    try {
      //重点方法,该方法是个抽象的方法,实现在子类中实现
      statement = instantiateStatement(connection);
      setStatementTimeout(statement, transactionTimeout);
      setFetchSize(statement);
      return statement;
    } catch (SQLException e) {
      closeStatement(statement);
      throw e;
    } catch (Exception e) {
      closeStatement(statement);
      throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
    }
  }
  abstract Statement instantiateStatement(Connection connection) throws SQLException;

SimpleStatementHandler中instantiateStatement方法的实现,调用connection.createStatement()

@Override
  protected Statement instantiateStatement(Connection connection) throws SQLException {
    if (mappedStatement.getResultSetType() != null) {
      return connection.createStatement(mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
    } else {
      return connection.createStatement();
    }
  }

PreparedStatementHandler中instantiateStatement方法的实现,调用connection.prepareStatement()生成,

@Override
  protected Statement instantiateStatement(Connection connection) throws SQLException {
    String sql = boundSql.getSql();
    if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
      String[] keyColumnNames = mappedStatement.getKeyColumns();
      if (keyColumnNames == null) {
        return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
      } else {
        return connection.prepareStatement(sql, keyColumnNames);
      }
    } else if (mappedStatement.getResultSetType() != null) {
      return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
    } else {
      return connection.prepareStatement(sql);
    }
  }

以上便完成了statement的创建。
前文提到其同时负责:PrepareStatement,CallableStatement输送Sql的语句的占位符。
使用ParameterHandler进行参数配置,方法为parameterize。其中调用了四大神器的ParameterHandler进行参数配置

public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
  }

操作对象的运行行为update,query。

int update(Statement statement)
      throws SQLException;

  <E> List<E> query(Statement statement, ResultHandler resultHandler)
      throws SQLException;

在BaseStatementHandler各个子类中重写了该方法
调用了PreparedStatement ps = (PreparedStatement) statement;ps.execute();
调用了四大神器的resultSetHandler进行结果配置

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

本文地址:https://blog.csdn.net/wsdfym/article/details/107592986

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网