mybatis3 源码深度解析-认识ParameterHandler参数处理器

大纲:

  • ParameterHandler 参数处理器的作用
  • ParameterHandler 接口方法介绍
  • ParameterHandler 默认实现类DefaultParameterHandler

ParameterHandler 参数处理器的作用

当使用 PreparedStatetment 或者 CallableStatetment对象执行 SQL 时,如果 SQL 语句中有参数占位符,在执行 SQL 语句前就需要将占位符替换为真实值.

ParameterHandler参数处理器的作用是在PreparedStatetmentHandler 或者 CallableStatetmentHandler操作对应的 Statement 执行数据库交互之前为参数占位符设置值

ParameterHandler 接口方法介绍

public interface ParameterHandler {
  Object getParameterObject();

  /**
   * 用于为 JDBC PreparedStatetment  或者 CallableStatetment对象 的参数占位符设置值
   * @param ps
   */
  void setParameters(PreparedStatement ps) throws SQLException;
}

ParameterHandler 默认实现类DefaultParameterHandler

  • ParameterHandler 接口只有一个默认实现类DefaultParameterHandler
public class DefaultParameterHandler implements ParameterHandler {
  private final TypeHandlerRegistry typeHandlerRegistry;
  private final MappedStatement mappedStatement;
  private final Object parameterObject;
  private final BoundSql boundSql;
  private final Configuration configuration;

  @Override
  public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    //1 获取所有参数映射信息
    List 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;
          //2 参数属性名称
          String propertyName = parameterMapping.getProperty();

          /**
           * 1 计算参数值的优先级是 先判断是不是属于语句的AdditionalParameter;
           * 2 其次参数是不是null;
           * 3 然后判断是不是属于注册类型;都不是,
           * 4 那估计参数一定是object或者map了,这就要借助于反射工具类MetaObject获取属性值了;
           */
          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())) {
            value = parameterObject;
          } else {
            //4 通过configuration对象提供的工厂方法创建反射工具类 MetaObject对象,通过反射获取属性值
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          //3 获取参数对应 TypeHandler 类型处理器
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            // 4 委托具体的类型处理器进行参数的设置, 经过 BaseTypeHandler=>再到IntegerTypeHandler 执行 ps.setXX()
            // jdbc下标从1开始,对于每个jdbcType, mybatis都提供了一个对应的Handler,具体可参考上文TypeHandler详解, 其内部调用的是PrepareStatement.setXXX进行设置。
            typeHandler.setParameter(ps, i + 1, value, jdbcType);
          } catch (TypeException | SQLException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          }
        }
      }
    }
  }

}
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章