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的設置參數方法。