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。

  

原文地址:https://www.cnblogs.com/zsg88/p/7571960.html