• MyBatis框架的使用及源码分析(十二) ParameterHandler


    在StatementHandler使用prepare()方法后,接下来就是使用ParameterHandler来设置参数,让我们看看它的定义: 

    package org.apache.ibatis.executor.parameter;  
      
    import java.sql.PreparedStatement;  
    import java.sql.SQLException;  
      
    /** 
     * A parameter handler sets the parameters of the {@code PreparedStatement} 
     * 
     * @author Clinton Begin 
     */  
    public interface ParameterHandler {  
      
      Object getParameterObject();  
      
      void setParameters(PreparedStatement ps)  
          throws SQLException;  
      
    }  
    

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

      

    DefaultParameterHandler是它的实现类:

    package org.apache.ibatis.scripting.defaults;  
      
    import java.sql.PreparedStatement;  
    import java.sql.SQLException;  
    import java.util.List;  
      
    import org.apache.ibatis.executor.ErrorContext;  
    import org.apache.ibatis.executor.parameter.ParameterHandler;  
    import org.apache.ibatis.mapping.BoundSql;  
    import org.apache.ibatis.mapping.MappedStatement;  
    import org.apache.ibatis.mapping.ParameterMapping;  
    import org.apache.ibatis.mapping.ParameterMode;  
    import org.apache.ibatis.reflection.MetaObject;  
    import org.apache.ibatis.session.Configuration;  
    import org.apache.ibatis.type.JdbcType;  
    import org.apache.ibatis.type.TypeException;  
    import org.apache.ibatis.type.TypeHandler;  
    import org.apache.ibatis.type.TypeHandlerRegistry;  
      
    /** 
     * @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);  
              }  
            }  
          }  
        }  
      }  
      
    }  
    

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

    重点看setParameters(),首先它读取了ParameterObject参数对象,然后用typeHandler对参数进行设置,而typeHandler里面需要对jdbcType和javaType进行处理,然后就设置参数了。也很好理解。所以当我们使用TypeHandler的时候完全可以控制如何设置SQL参数。设置参数,其实就是你在sql语句中配置的java对象和jdbc类型对应的关系,例如#{id,jdbcType=INTEGER},id默认类型是javaType=class java.lang.Integer。

      

  • 相关阅读:
    百度脑图源码
    H5与Native交互的实现
    【GOF23设计模式】建造者模式
    【GOF23设计模式】工厂模式
    【GOF23设计模式】单例模式
    Linux符设备驱动编程
    linux多线程编程——读者优先、写者优先问题
    建立makefile
    构建交叉开发环境
    Failed to create the part's controls解决方法
  • 原文地址:https://www.cnblogs.com/zsg88/p/7571960.html
Copyright © 2020-2023  润新知