聊聊Mybatis的BaseStatementHandler的三个子类

今天我们继续聊StatementHandler的实现类

PreparedStatementHandler

PreparedStatementHandler处理的是包含?占位符的sql语句,所以它需要进行参数绑定:

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

我们通过parameterize()方法的实现就能看出,这个方法是设置参数的,而其他的方法和和StatementHandler整体差不多

SimpleStatementHandler

SimpleStatementHandler对没有占位符的sql语句的StatementHandler类,看一下它的update()方法的实现:

对于insert update delete语句都会执行这个方法

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;
  }
  1. 获取到sql
  2. 获取KeyGenerator实例,如果是Jdbc3KeyGenerator实例,调用execute(sql, Statement.RETURN_GENERATED_KEYS)方法执行sql,如果是SelectKeyGenerator,调用execute(sql)执行sql,然后执行keyGenerator.processAfter()方法将主键存入MappedStatement对象中
  3. 通过getUpdateCount()方法获取影响行数并返回

有的同学会产生疑问,为什么没有调用keyGenerator.processBefore()方法呢?其实在BaseStatementHandler的构造方法中就产生调用了

对于查询方法就更简单了,获取sql调用statement.execute(sql)进行执行,然后resultSetHandler.handleResultSets(statement)进行结果处理,返回list集合

CallableStatementHandler

而CallableStatementHandler也是继承BaseStatementHandler,实现抽象方法instantiateStatement(),实现方法中返回CallableStatement对象,而他的其他查询更新等方法都调用了resultSetHandler.handleOutputParameters(cs)进行参数的输出

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

从代码中我们和SimpleStatementHandler的update代码对比,除了Statement不同,整体一样,多了个步骤就是对参数的输出:resultSetHandler.handleOutputParameters(cs);

总结

这篇文章我们讲了继承BaseStatementHandler抽象类的三个类,PreparedStatementHandler处理的是带有问号占位符的sql语句,它需要做参数处理,而SimpleStatementHandler处理没有占位符的sql语句,所以不需要进行参数的处理,CallableStatementHandler和PreparedStatementHandler差不多,也需要做参数的设置,除此之外,它还需要处理的就是进行代码参数的输出