程序员Mybatis源码之路

ParameterHandler

2020-08-30  本文已影响0人  93张先生

ParameterHandler

ParameterHandler 是一个 SQL 实参处理器,主要功能是为 SQL 语句 绑定实参,使用传入的实参替换 SQL 吾句的中 ? 占位符。

public interface ParameterHandler {

 Object getParameterObject();

 void setParameters(PreparedStatement ps)
     throws SQLException;

}

DefaultParameterHandler

DefaultParameterHandler 是 ParameterHandler 接口唯一默认实现类。

在 BoundSql 中记录的 SQL 语句中可能包含"?"占位符,而每个"?"占位符都对应了 BoundSql.parameterMappings 集合中的一个元素,在该 ParameterMapping 中记录了对应的参数名称以及该参数的相关属性。

public class DefaultParameterHandler implements ParameterHandler {
  // TypeHandlerRegistry 对象,管理 MyBatis 中的 全部 TypeHandler 对象
  private final TypeHandlerRegistry typeHandlerRegistry;
  // MappedSt tement 对象,其中记录 SQL 节点相应的配置信息
  private final MappedStatement mappedStatement;
  // 用户传入的实参对象
  private final Object parameterObject;
  // 包含 "?" 占位符的,包含数据库将要执行的 sql 语句的对象
  private final BoundSql boundSql;
  private final Configuration configuration;

  public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
    this.mappedStatement = mappedStatement;
    this.configuration = mappedStatement.getConfiguration();
    this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
    this.parameterObject = parameterObject;
    this.boundSql = boundSql;
  }

  @Override
  public Object getParameterObject() {
    return parameterObject;
  }

  /**
   * 将 BoundSql 中,含有 "?" 占位符替换为实参。
   * setParameters 会遍历 BoundSql.parameterMappings 集合中记录的 ParameterMapping 对象,井根据其中记录的参数名称查找相应实参 然后与 SQL 语句绑定。
   * @param ps
   */
  @Override
  public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    // 取出 sql 中的参数映射列表
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
      for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        // 过滤掉存储过程中的输出参数
        if (parameterMapping.getMode() != ParameterMode.OUT) {
          // 记录绑定的实参
          Object value;
          // 获取参数名称
          String propertyName = parameterMapping.getProperty();
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            // 获取对应的实参位
            value = boundSql.getAdditionalParameter(propertyName);
          //  整个实参为空
          } else if (parameterObject == null) {
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            // 实参可以直接通过 TypeHandler 转换成 JdbcType
            value = parameterObject;
          } else {
            // 获取对象中相应的属性位或查找 Map 对象中位
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          // 获取 ParameterMapping 中设置的 TypeHandler 对象
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            // 通过 TypeHandler setParameter() 方法会调用 PreparedStatement.set *() 方法,为 SQL 语句绑定相应的实参
            typeHandler.setParameter(ps, i + 1, value, jdbcType);
          } catch (TypeException | SQLException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          }
        }
      }
    }
  }

}
上一篇 下一篇

猜你喜欢

热点阅读