Hello World

mybatis四大接口之 StatementHandler

1. 继承结构

    

 

  1. StatementHandler:顶层接口
  2. BaseStatementHandler : 实现顶层接口的抽象类,实现了部分接口,并定义了一个抽象方法
  3. SimpleStatementHandler:对应JDBC中常用的Statement接口,用于简单SQL的处理;
  4. PreparedStatementHandler:对应JDBC中的PreparedStatement,预编译SQL的接口;
  5. CallableStatementHandler:对应JDBC中CallableStatement,用于执行存储过程相关的接口;
  6. RoutingStatementHandler:这个接口是以上三个接口的路由,没有实际操作,只是负责上面三个StatementHandler的创建及调用。

2. BaseStatementHandler 

  三个子类都 继承 prepare() 方法,并没有重写该方法。该方法中调用了方法 instantiateStatement ();

   instantiateStatement 是一个抽象方法,根据一个Connection 返回一个Statement 对象;

  三个子类都实现了该方法,分别返回了 StatementPrepareStaement 和 CallableStatement 对象。

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

 3. 抽象类的子类实现的接口方法

  三个子类都实现了 update() ,batch() ,query()。

  在对应的方法中将传入的 Statement 对象转型为 具体的 Statement 类型进行相应的操作。

  以 PrepareStatement 示例:

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

4. RoutingStatementHandler

  该类采用了代理模式(静态代理);

  该类直接实现了 StatmentHandler 接口,实现了接口的全部方法。

  该类持有一个 StatmentHandler  的实例,并在创建该类时根据传入的 MappedStatement 的 type 创建不同的 Statement 实例,然后通过这个具体的实例去实现相应的操作。

public class RoutingStatementHandler implements StatementHandler {

  private final StatementHandler delegate;

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

  }

  @Override
  public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
    return delegate.prepare(connection, transactionTimeout);
  }

  @Override
  public void parameterize(Statement statement) throws SQLException {
    delegate.parameterize(statement);
  }

  @Override
  public void batch(Statement statement) throws SQLException {
    delegate.batch(statement);
  }

    // 其他方法同理
    ...
}

 

posted @ 2018-12-05 20:33  小小忧愁米粒大  阅读(1501)  评论(0编辑  收藏  举报
瞅啥瞅,好好看书