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

mybatis-StatementHandler解析

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

概述

StatementHandler,Statement处理器,主要是和jdbc中的Statement交互。

public interface StatementHandler {

  /**
   * 创建Statement
   * @param connection
   * @param transactionTimeout
   * @return
   * @throws SQLException
   */
  Statement prepare(Connection connection, Integer transactionTimeout)
      throws SQLException;

  /**
   * 设置参数到statement
   * @param statement
   * @throws SQLException
   */
  void parameterize(Statement statement)
      throws SQLException;

  /**
   * 批量支持
   * @param 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();

}

提供的能力:

  • 创建Statement实例
  • 设置参数
  • 执行sql

类图结构:

在这里插入图片描述
看这个结构和Executor是不是特别像。

BaseStatementHandler依旧是通用逻辑处理(异常处理、通用参数设置)

SimpleStatementHandler:普通Statement处理器。

PreparedStatementHandler:PrepareStatement处理器。

CallableStatementHandler:CallableStatement处理器。

RoutingStatementHandler:封装路由逻辑。

BaseStatementHandler

基础Statement处理器

 protected final Configuration configuration;
  /**
   * 对象工厂,用于创建返回值类型实例
   */
  protected final ObjectFactory objectFactory;
  protected final TypeHandlerRegistry typeHandlerRegistry;
  /**
   * 数据集处理器
   */
  protected final ResultSetHandler resultSetHandler;
  /**
   * 参数处理器
   */
  protected final ParameterHandler parameterHandler;
  // 执行器
  protected final Executor executor;
  // 映射Statement
  protected final MappedStatement mappedStatement;
  // 分页参数
  protected final RowBounds rowBounds;
  // 动态sql
  protected BoundSql boundSql;

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

StatementHandler 在构造函数中会创建ParameterHandler和ResultSetHandler用于参数和返回值的处理。

prepare

@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
  ErrorContext.instance().sql(boundSql.getSql());
  Statement statement = null;
  try {
    /*
     * 对应创建三种Statement,对应StatementType
     * simple
     * prepare
     * callable(用来调用存储过程)
     */
    statement = instantiateStatement(connection);

    // statement通用参数设置
    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);
  }
}

实例化Statement实例由子类实现,超时时间、fetch大小通用设置。

SimpleStatementHandler

instantiateStatement

实例化Statement,

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

通过Connection创建普通Statement。

update

 @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 {
      // 执行sql 返回值
      statement.execute(sql);
      rows = statement.getUpdateCount();
    }
    return rows;
  }

更新方法,增加了对主键的处理。

query

@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
  String sql = boundSql.getSql();
  statement.execute(sql);

  // 返回值处理
  return resultSetHandler.handleResultSets(statement);
}

直接执行,结果值处理交给ResultHandler。

PreparedStatementHandler

对应PrepareStatement

instantiateStatement

@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() == ResultSetType.DEFAULT) {
    return connection.prepareStatement(sql);
  } else {
    return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
  }
}

其实也只是通过Connection创建PrepareStatement

update

@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;
}

逻辑比较简单,执行sql后,主键生成器执行。

query

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

和Simple一样。

CallableStatementHandler(存储过程略过)

RoutingStatementHandler

路由Statement处理器

public class RoutingStatementHandler implements StatementHandler {

 
  private final StatementHandler delegate;

  public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {

    // 根据类型创建statement实例
    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其实就是在构造函数内封装了路由的逻辑,将这个switch case包装了起来,实际的实现还是委托给实际实现类完成。一个不错的小设计,可以借鉴一下。

总结

StatementHandler主要是封装了和JDBC-Statement的实例化,设置参数和返回值转换在ParameterHandler和ResultSetHandler。层层拆分,职责清晰。

本文地址:https://blog.csdn.net/qq_28695733/article/details/107198818

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

相关文章:

验证码:
移动技术网