美文网首页
mybatis四大神器之ParameterHandler

mybatis四大神器之ParameterHandler

作者: ajajaj | 来源:发表于2020-07-28 10:12 被阅读0次

ParameterHandler顾名思义是mybatis中的参数处理器,负责为 PreparedStatement 的 sql 语句参数动态赋值,这个接口很简单只有两个方法:

public interface ParameterHandler {
    //读取参数 
    Object getParameterObject();
     //用于对PreparedStatement的参数赋值.
    void setParameters(PreparedStatement var1) throws SQLException;
}

PreparedStatement的继承体系

只有一个实现类DefaultParameterHandler

image

ParameterHandler对象创建

参数处理器对象是在创建StatementHandler对象同时被创建的.由Configuration对象负责创建.

image

创建时 传入三个对象:执行SQL对应的配置信息

  • MappedStatement
  • 参数对象Object
  • SQL的BoundSql

一个BoundSql对象,代表了一次sql语句的实际执行,而SqlSource对象的责任,就是根据传入的参数对象,动态计算出这个BoundSql,也就是说Mapper文件中的节点的计算,是由SqlSource对象完成的。SqlSource最常用的实现类是DynamicSqlSource

ParameterHandler参数的由来

   @Test
     public void Test01(){
            DeptDao dao =  session.getMapper(DeptDao.class);
            Dept dept = dao.findByDeptNo(10);
            System.out.println(dept.getDname());
     }

上述命令的实参10是如何添加到对应的SQL语句中的.

 <select id="findByDeptNo" resultType="dept">
        <include refid="DeptFindSql"></include>
        where deptno = #{deptNo}
   </select>

在mybatis中,使用动态代理模式.当dao.findByDeptNo(10)将要执行时;会被JVM进行拦截
交给mybatis中的代理实现类MapperProxy的invoke方法中

image

然后在一步步交给ParameterHandler中setParameter方法,将参数交给对应占位符

PrepareStatment的参数赋值

public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    // parameterMappings是对#{}里给出的参数的封装,sql是一个参数话sql(sql中有占位符)
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    // 参数化sql需要设置参数,遍历这个参数列表,把参数设置到PreparedStatement中
    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())) {
            value = parameterObject;// 实参可以直接通过TypeHandler转换为JdbcType
          } else {
          // 获取对象中相应的属性或查找Map对象中的值
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          // 从parameterMapping中获取typeHandler对象
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          //从从parameterMapping获取参数对应的jdbcType
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            // 通过TypeHandler.setParameter方法会调用PreparedStaement.set*()方法
            // 为SQL语句绑定相应实参
            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);
          }
        }
      }
    }
  }

原文地址

http://cbaj.gitee.io/blog/2020/07/21/mybatis%E5%9B%9B%E5%A4%A7%E7%A5%9E%E5%99%A8%E4%B9%8BParameterHandler/#more

相关文章

网友评论

      本文标题:mybatis四大神器之ParameterHandler

      本文链接:https://www.haomeiwen.com/subject/eooxrktx.html