Mybatis—ParameterHandler

  使用PreparedStatement或者CallableStatement对执行SQL语句时,如果SQL语句中有参数占位符,那么在之前就需要为参数占位符设置值。ParameterHandler的主要职责就是给参数占位符赋值,在赋值时又结合使用了TypeHandler来对目标参数进行Java和JDBC类型之间的转换。
  ParameterHandler相对于Mybatis其它的组件来讲是相比较简单的,其接口只定义了两个方法:

  1. getParameterObject,用于获取执行Mapper时传入的参数对象;
  2. setParameters,用于为PreparedStatement或者CallableStatement对象设置参数值。
public interface ParameterHandler {

  Object getParameterObject();

  void setParameters(PreparedStatement ps) throws SQLException;

}

DefaultParameterHandler

  Mybatis为ParameterHandler提供了一个默认实现类-DefaultParameterHandler,其实现了getParameterObject方法和setParameters方法。getParameterObject方法的实现逻辑相当简单,就是将构造方法传入的parameterObject原样返回。
  setParameters方法的实现逻辑相比之下就要复杂很多,DefaultParameterHandler首先获取Mapper配置中的参数映射ParameterMapping;然后遍历所有ParameterMapping,根据其参数名称获取对应的值,最后调用当前参数对应的TypeHandler来为占位符赋值。

@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)) { 
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            // 如果类型处理器中有对应的typeHandler,直接赋值
            value = parameterObject;
          } else {
            // 如果没有对应的typeHandler,将参数转化为MetaObject反射工具类
            // 然后从元数据类中寻找当前参数的值
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          // 获取typeHandler类型处理器
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          // 获取JdbcType Java类型定义
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            // 调用typeHandler的setParameter方法完成占位符参数的赋值
            typeHandler.setParameter(ps, i + 1, value, jdbcType);
          } catch (TypeException | SQLException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          }
        }
      }
    }
}

  结合源代码,可以概括为下述几个步骤:

  1. 从BoundSql类中获取当前SQL语句中的占位符参数ParameterMapping定义,如果不为空就直接遍历ParameterMapping定义,为每一个占位符参数赋值;
  2. 如果占位符参数的ParameterMode不是OUT就进行赋值处理;
  3. 如果在类型处理器中找到对应的typeHandler,就直接赋值;
  4. 如果在没有找到对应的typeHandler,将参数转化为MetaObject反射工具类,然后从元数据类中寻找当前参数的值;
  5. 得到value值之后,再获取在ParameterMapping中定义的typeHandler类型处理器和Java类型;
  6. 调用typeHandler类型处理器的setParameter方法,将value值设置到当前的PreparedStatement对象。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐只乐之

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值