ParameterHandler显然是用来处理参数的,主要是用来设置PreparedStatement的参数,接口只有两个方法,一个是获取参数对象,一个是设置PreparedStatement的参数。PreparementStatement会
public interface ParameterHandler {
Object getParameterObject();
void setParameters(PreparedStatement ps) throws SQLException;
}
此接口只有一个实现类:DefaultParameterHandler。 可以看到在创建StatementHandler实例调用BaseStatementHandler的构造器时,会创建ParameterHandler
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
}
这里我们重点看一下setParameters方法的实现:
public class DefaultParameterHandler implements ParameterHandler {
@Override
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
// 会从BoundSql里面拿到ParameterMappings对象
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
// 非存储过程的OUT类型
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())) {
// 如果有对应的typeHandler则,value就为paremeterObject
value = parameterObject;
} else {
// 否则创建一个新的MetaObject
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
// 拿到TypeHandler和JdbcType
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
// 如果两个都为空,则设置jdbcType为JdbcType.OTHER
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
// 调用typeHandler的setParameter来设置参数,最终会根据类型调用PreparementStatement的setXXX方法,来设置对应的值
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException | SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
}
可以看到ParamenterHandler相对比较简单,主要是根据配置解析的ParameterMapping(参数映射)找到对应的TypeHandler和JdbcType,最终会调用到PreparedStatement的设置参数方法。