Mybatis参数变量替换流程

Mybatis自带的日志没有把可执行sql语句打印出来,跟踪了一下其参数替换流程记录下来,详细的参数替换原理可以参考大牛的博文《深入了解MyBatis参数

下面是字符串参数替换的流程,红色标注部分为主要赋值函数

1.org.apache.ibatis.executor.SimpleExecutor
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Connection connection = this.getConnection(statementLog);
    Statement stmt = handler.prepare(connection, this.transaction.getTimeout());
    handler.parameterize(stmt);
    return stmt;
}
2.org.apache.ibatis.executor.statement.RoutingStatementHandler
public void parameterize(Statement statement) throws SQLException {
    this.delegate.parameterize(statement);
}
3.org.apache.ibatis.executor.statement.PreparedStatementHandler
public void parameterize(Statement statement) throws SQLException {
    this.parameterHandler.setParameters((PreparedStatement)statement);
}
4.org.apache.ibatis.scripting.defaults.DefaultParameterHandler
public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(this.mappedStatement.getParameterMap().getId());
    List parameterMappings = this.boundSql.getParameterMappings();
    if(parameterMappings != null) {
        for(int i = 0; i < parameterMappings.size(); ++i) {
            ParameterMapping parameterMapping = (ParameterMapping)parameterMappings.get(i);
            if(parameterMapping.getMode() != ParameterMode.OUT) {
                String propertyName = parameterMapping.getProperty();
                Object value;
                if(this.boundSql.hasAdditionalParameter(propertyName)) {
                    value = this.boundSql.getAdditionalParameter(propertyName);
                } else if(this.parameterObject == null) {
                    value = null;
                } else if(this.typeHandlerRegistry.hasTypeHandler(this.parameterObject.getClass())) {
                    value = this.parameterObject;
                } else {
                    MetaObject typeHandler = this.configuration.newMetaObject(this.parameterObject);
                    value = typeHandler.getValue(propertyName);
                }

                TypeHandler var12 = parameterMapping.getTypeHandler();
                JdbcType jdbcType = parameterMapping.getJdbcType();
                if(value == null && jdbcType == null) {
                    jdbcType = this.configuration.getJdbcTypeForNull();
                }

                try {
                    var12.setParameter(ps, i + 1, value, jdbcType);
                } catch (TypeException var10) {
                    throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + var10, var10);
                } catch (SQLException var11) {
                    throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + var11, var11);
                }
            }
        }
    }

}
5.org.apache.ibatis.type.BaseTypeHandler
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
    if(parameter == null) {
        if(jdbcType == null) {
            throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
        }

        try {
            ps.setNull(i, jdbcType.TYPE_CODE);
        } catch (SQLException var7) {
            throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " + "Cause: " + var7, var7);
        }
    } else {
        try {
            this.setNonNullParameter(ps, i, parameter, jdbcType);
        } catch (Exception var6) {
            throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . " + "Try setting a different JdbcType for this parameter or a different configuration property. " + "Cause: " + var6, var6);
        }
    }

}
6.org.apache.ibatis.type.UnknownTypeHandler
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
    TypeHandler handler = this.resolveTypeHandler(parameter, jdbcType);
    handler.setParameter(ps, i, parameter, jdbcType);
}
7.org.apache.ibatis.type.StringTypeHandler
public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
    ps.setString(i, parameter);
}
8.org.apache.ibatis.logging.jdbc.PreparedStatementLogger
注意ps.setString是通过反射调用的invoke函数
原理是实现InvocationHandler接口,自动调用invoke函数
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable;
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
    try {
        if(Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, params);
        } else {
            ResultSet t1;
            if(EXECUTE_METHODS.contains(method.getName())) {
                if(this.isDebugEnabled()) {
                    this.debug("Parameters: " + this.getParameterValueString(), true);
                }

                this.clearColumnInfo();
                if("executeQuery".equals(method.getName())) {
                    t1 = (ResultSet)method.invoke(this.statement, params);
                    return t1 == null?null:ResultSetLogger.newInstance(t1, this.statementLog, this.queryStack);
                } else {
                    return method.invoke(this.statement, params);
                }
            } else if(SET_METHODS.contains(method.getName())) {
                if("setNull".equals(method.getName())) {
                    this.setColumn(params[0], (Object)null);
                } else {
                    this.setColumn(params[0], params[1]);
                }

                return method.invoke(this.statement, params);
            } else if("getResultSet".equals(method.getName())) {
                t1 = (ResultSet)method.invoke(this.statement, params);
                return t1 == null?null:ResultSetLogger.newInstance(t1, this.statementLog, this.queryStack);
            } else if("getUpdateCount".equals(method.getName())) {
                int t = ((Integer)method.invoke(this.statement, params)).intValue();
                if(t != -1) {
                    this.debug("   Updates: " + t, false);
                }

                return Integer.valueOf(t);
            } else {
                return method.invoke(this.statement, params);
            }
        }
    } catch (Throwable var5) {
        throw ExceptionUtil.unwrapThrowable(var5);
    }
}

你可能感兴趣的:(java,mybatis)