Mybatis原始碼分析之引數對映及處理ParameterHandler
阿新 • • 發佈:2019-02-07
ParameterHandler是用來設定引數規則的,當StatementHandler呼叫prepare方法之後,接下來就是呼叫它來進行設定引數。
ParameterHandler介面:
public interface ParameterHandler {
Object getParameterObject();
void setParameters(PreparedStatement ps)
throws SQLException;
}
getParameterObject是用來獲取引數的,setParameters(PreparedStatement ps)是用來設定引數的,相當於對sql中所有的引數都執行ps.setXXX(value);ParameterHandler的預設實現類是DefaultParameterHandler,其實現了介面中定義的兩個方法。
getParameterObject是獲取引數,這個引數值就是你傳遞進來的值,可能是個實體、map或單個基本型別資料。
@Override
public Object getParameterObject() {
return parameterObject;
}
設定引數,其實就是你在sql語句中配置的java物件和jdbc型別對應的關係#{id,jdbcType=INTEGER},id預設型別是javaType=class java.lang.Integer。這樣就設定了一個引數值對應的jdbcType了//設定引數 @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); } } } } }
完整的DefaultParameterHandler原始碼如下:
/** * @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); } } } } } }