ParameterHandler是用来设置参数规则的,当StatementHandler调用prepare方法之后,接下来就是调用它来进行设置参数。

ParameterHandler接口:

public interface ParameterHandler {

  Object getParameterObject();

  void setParameters(PreparedStatement ps)
      throws SQLException;

}

getParameterObject是用来获取参数的,setParameters(PreparedStatement ps)是用来设置参数的,相当于对sql中所有的参数都执行ps.setXXX(value);

ParameterHandler的默认实现类是DefaultParameterHandler,其实现了接口中定义的两个方法。

getParameterObject是获取参数,这个参数值就是你传递进来的值,可能是个实体、map或单个基本类型数据。

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

设置参数,其实就是你在sql语句中配置的java对象和jdbc类型对应的关系#{id,jdbcType=INTEGER},id默认类型是javaType=class java.lang.Integer。

//设置参数
  @Override
  public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
	//获取所有参数,ParameterMapping是java类型和jdbc类型的对应关系
    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())) {
			 //如果是单个值则直接赋值
            value = parameterObject;
          } else {
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
         //获取参数值对应的jdbc类型
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
	   //设置参数值和jdbc类型的对应关系
            typeHandler.setParameter(ps, i + 1, value, jdbcType);
          } catch (TypeException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          } catch (SQLException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          }
        }
      }
    }
  }

这样就设置了一个参数值对应的jdbcType了

完整的DefaultParameterHandler源码如下:

/**
 * @author Clinton Begin
 * @author Eduardo Macarron
 */
public class DefaultParameterHandler implements ParameterHandler {

  private final TypeHandlerRegistry typeHandlerRegistry;

  private final MappedStatement mappedStatement;
  //所有的参数值
  private final Object parameterObject;
  private BoundSql boundSql;
  private 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;
  }
  //设置参数
  @Override
  public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
	//获取所有参数,ParameterMapping是java类型和jdbc类型的对应关系
    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())) {
			 //如果是单个值则直接赋值
            value = parameterObject;
          } else {
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
		  //获取参数值对应的jdbc类型
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
			//设置参数值和jdbc类型的对应关系
            typeHandler.setParameter(ps, i + 1, value, jdbcType);
          } catch (TypeException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          } catch (SQLException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          }
        }
      }
    }
  }

}

Mybatis源码分析之参数映射及处理ParameterHandler的更多相关文章

  1. MyBatis源码分析1 参数映射分析

    首先我们拿出之前的代码,在如图位置打上断点,开始调试 我们规定了一个mapper接口,而调用了mapper接口的getEmpByIdAndLastName,我们并没有实现这个接口,这是因为Mybati ...

  2. Mybatis源码分析之参数处理

    Mybatis对参数的处理是值得推敲的,不然在使用的过程中对发生的一系列错误直接懵逼了. 以前遇到参数绑定相关的错误我就是直接给加@param注解,也稀里糊涂地解决了,但是后来遇到了一些问题推翻了我的 ...

  3. MyBatis 源码分析 - 映射文件解析过程

    1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...

  4. 精尽MyBatis源码分析 - MyBatis初始化(二)之加载Mapper接口与XML映射文件

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  5. MyBatis源码分析-MyBatis初始化流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  6. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  7. 【MyBatis源码分析】select源码分析及小结

    示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...

  8. Mybatis源码分析-StatementHandler

    承接前文Mybatis源码分析-BaseExecutor,本文则对通过StatementHandler接口完成数据库的CRUD操作作简单的分析 StatementHandler#接口列表 //获取St ...

  9. mybatis源码分析(一)

    mybatis源码分析(sqlSessionFactory生成过程) 1. mybatis框架在现在各个IT公司的使用不用多说,这几天看了mybatis的一些源码,赶紧做个笔记. 2. 看源码从一个d ...

随机推荐

  1. 电力 Web SCADA 工控组态编辑器

    前言 SVG 并非仅仅是一种图像格式, 由于它是一种基于 XML 的语言,也就意味着它继承了 XML 的跨平台性和可扩展性,从而在图形可重用性上迈出了一大步.如 SVG 可以内嵌于其他的 XML 文档 ...

  2. 【微信小程序】对微信http请求API的封装,方便对错误码进行处理

    /**   * App 微信配置文件app.js   * author: nujey   * versions: 1.0.0   */   App({   /**   * @param {Object ...

  3. [LeetCode] Keyboard Row 键盘行

    Given a List of words, return the words that can be typed using letters of alphabet on only one row' ...

  4. [HAOI 2008]木棍分割

    Description 题库链接 有 \(n\) 根木棍,第 \(i\) 根木棍的长度为 \(L_i\) , \(n\) 根木棍依次连结了一起,总共有 \(n-1\) 个连接处.现在允许你最多砍断 \ ...

  5. [SDOI2017]序列计数

    题目描述 Alice想要得到一个长度为nn的序列,序列中的数都是不超过mm的正整数,而且这nn个数的和是pp的倍数. Alice还希望,这nn个数中,至少有一个数是质数. Alice想知道,有多少个序 ...

  6. ●BZOJ 2154 Crash的数字表格

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2154 题解: 莫比乌斯反演. 题意还是很清楚的,就不赘述了. 显然有 $ANS=\sum_{ ...

  7. 51Nod 1753 相似子串

    题目大意: 两个字符串相似定义为: 1.两个字符串长度相等 2.两个字符串对应位置上有且仅有至多一个位置所对应的字符不相同 给定一个字符串,每次询问两个子串在给定的规则下是否相似.给定的规则指每次给出 ...

  8. [bzoj4849][Neerc2016]Mole Tunnels

    来自FallDream的博客,未经允许,请勿转载,谢谢 貌似是省队集训女队讲的题... 今天在bzoj找一道题无果,但是翻到了这道就顺便写了下. 鼹鼠们在底下开凿了n个洞,由n-1条隧道连接,对于任意 ...

  9. 习题10-1 UVA 11040(无聊水一水)

    题意: 给你一个残缺的塔,每个数字由他下面左右两个数相加得.给你其中一部分,要求输出全部的数字. #include <iostream> #include <cstdio> # ...

  10. [BZOJ]1047 理想的正方形(HAOI2007)

    真·水题.小C本来是不想贴出来的,但是有一股来自东方的神秘力量催促小C发出来. Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和 ...