首页 > 代码库 > MyBatis源码分析(二)语句处理器

MyBatis源码分析(二)语句处理器

StatementHandler

语句处理器,主要负责语句的创建、参数的设置、语句的执行。不负责结果集的处理。

Statement prepare(Connection connection, Integer transactionTimeout) throws SQLExceptionvoid parameterize(Statement statement) throws SQLExceptionvoid batch(Statement statement) throws SQLExceptionint update(Statement statement) throws SQLExceptionList<E> query(Statement statement, ResultHandler resultHandler) throws SQLExceptionCursor<E> queryCursor(Statement statement) throws SQLException

 

BaseStatementHandler

实现公共部分,具体差异通过抽象方法,留给子类实现。

@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);    }  }protected abstract Statement instantiateStatement(Connection connection) throws SQLException;

 

首先语句级别的配置,其次配置文件中的配置。

protected void setStatementTimeout(Statement stmt, Integer transactionTimeout) throws SQLException {    Integer queryTimeout = null;    if (mappedStatement.getTimeout() != null) {      queryTimeout = mappedStatement.getTimeout();    } else if (configuration.getDefaultStatementTimeout() != null) {      queryTimeout = configuration.getDefaultStatementTimeout();    }    if (queryTimeout != null) {      stmt.setQueryTimeout(queryTimeout);    }    StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);  }

 

首先语句级别的配置,其次配置文件中的配置。

 protected void setFetchSize(Statement stmt) throws SQLException {    Integer fetchSize = mappedStatement.getFetchSize();    if (fetchSize != null) {      stmt.setFetchSize(fetchSize);      return;    }    Integer defaultFetchSize = configuration.getDefaultFetchSize();    if (defaultFetchSize != null) {      stmt.setFetchSize(defaultFetchSize);    }  }

 

StatementUtil

如果两个参数都有值,设置较小的那一个。

public static void applyTransactionTimeout(Statement statement, Integer queryTimeout, Integer transactionTimeout) throws SQLException {    if (transactionTimeout == null){      return;    }    Integer timeToLiveOfQuery = null;    if (queryTimeout == null || queryTimeout == 0) {      timeToLiveOfQuery = transactionTimeout;    } else if (transactionTimeout < queryTimeout) {      timeToLiveOfQuery = transactionTimeout;    }    if (timeToLiveOfQuery != null) {      statement.setQueryTimeout(timeToLiveOfQuery);    }  }

 

SimpleStatementHandler

无参数sql语句的执行。

@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();    }  }  @Override  public void parameterize(Statement statement) throws SQLException {    // N/A  }@Override  public int update(Statement statement) throws SQLException {    String sql = boundSql.getSql();    Object parameterObject = boundSql.getParameterObject();    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();    int rows;    if (keyGenerator instanceof Jdbc3KeyGenerator) {      statement.execute(sql, Statement.RETURN_GENERATED_KEYS);      rows = statement.getUpdateCount();      keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);    } else if (keyGenerator instanceof SelectKeyGenerator) {      statement.execute(sql);      rows = statement.getUpdateCount();      keyGenerator.processAfter(executor, mappedStatement, statement, parameterObject);    } else {      statement.execute(sql);      rows = statement.getUpdateCount();    }    return rows;  }  @Override  public void batch(Statement statement) throws SQLException {    String sql = boundSql.getSql();    statement.addBatch(sql);  }  @Override  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {    String sql = boundSql.getSql();    statement.execute(sql);    return resultSetHandler.<E>handleResultSets(statement);  }  @Override  public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {    String sql = boundSql.getSql();    statement.execute(sql);    return resultSetHandler.<E>handleCursorResultSets(statement);  }

 

PreparedStatementHandler

参数化sql语句的执行。

@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);    }  }  @Override  public void parameterize(Statement statement) throws SQLException {    parameterHandler.setParameters((PreparedStatement) statement);  }@Override  public int update(Statement statement) throws SQLException {    PreparedStatement ps = (PreparedStatement) statement;    ps.execute();    int rows = ps.getUpdateCount();    Object parameterObject = boundSql.getParameterObject();    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();    keyGenerator.processAfter(executor, mappedStatement, ps, parameterObject);    return rows;  }  @Override  public void batch(Statement statement) throws SQLException {    PreparedStatement ps = (PreparedStatement) statement;    ps.addBatch();  }  @Override  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {    PreparedStatement ps = (PreparedStatement) statement;    ps.execute();    return resultSetHandler.<E> handleResultSets(ps);  }  @Override  public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {    PreparedStatement ps = (PreparedStatement) statement;    ps.execute();    return resultSetHandler.<E> handleCursorResultSets(ps);  }

 

CallableStatementHandler

存储过程的执行。

@Override  protected Statement instantiateStatement(Connection connection) throws SQLException {    String sql = boundSql.getSql();    if (mappedStatement.getResultSetType() != null) {      return connection.prepareCall(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);    } else {      return connection.prepareCall(sql);    }  }  @Override  public void parameterize(Statement statement) throws SQLException {    registerOutputParameters((CallableStatement) statement);    parameterHandler.setParameters((CallableStatement) statement);  }@Override  public int update(Statement statement) throws SQLException {    CallableStatement cs = (CallableStatement) statement;    cs.execute();    int rows = cs.getUpdateCount();    Object parameterObject = boundSql.getParameterObject();    KeyGenerator keyGenerator = mappedStatement.getKeyGenerator();    keyGenerator.processAfter(executor, mappedStatement, cs, parameterObject);    resultSetHandler.handleOutputParameters(cs);    return rows;  }  @Override  public void batch(Statement statement) throws SQLException {    CallableStatement cs = (CallableStatement) statement;    cs.addBatch();  }  @Override  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {    CallableStatement cs = (CallableStatement) statement;    cs.execute();    List<E> resultList = resultSetHandler.<E>handleResultSets(cs);    resultSetHandler.handleOutputParameters(cs);    return resultList;  }  @Override  public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {    CallableStatement cs = (CallableStatement) statement;    cs.execute();    Cursor<E> resultList = resultSetHandler.<E>handleCursorResultSets(cs);    resultSetHandler.handleOutputParameters(cs);    return resultList;  }

 

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

 

MyBatis源码分析(二)语句处理器