ParameterHandler
ParameterHandler 是一个 SQL 实参处理器,主要功能是为 SQL 语句 绑定实参,使用传入的实参替换 SQL 吾句的中 ? 占位符。
public interface ParameterHandler {
Object getParameterObject();
void setParameters(PreparedStatement ps)
throws SQLException;
}
DefaultParameterHandler
DefaultParameterHandler 是 ParameterHandler 接口唯一默认实现类。
在 BoundSql 中记录的 SQL 语句中可能包含"?"占位符,而每个"?"占位符都对应了 BoundSql.parameterMappings 集合中的一个元素,在该 ParameterMapping 中记录了对应的参数名称以及该参数的相关属性。
public class DefaultParameterHandler implements ParameterHandler {
// TypeHandlerRegistry 对象,管理 MyBatis 中的 全部 TypeHandler 对象
private final TypeHandlerRegistry typeHandlerRegistry;
// MappedSt tement 对象,其中记录 SQL 节点相应的配置信息
private final MappedStatement mappedStatement;
// 用户传入的实参对象
private final Object parameterObject;
// 包含 "?" 占位符的,包含数据库将要执行的 sql 语句的对象
private final BoundSql boundSql;
private final 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;
}
/**
* 将 BoundSql 中,含有 "?" 占位符替换为实参。
* setParameters 会遍历 BoundSql.parameterMappings 集合中记录的 ParameterMapping 对象,井根据其中记录的参数名称查找相应实参 然后与 SQL 语句绑定。
* @param ps
*/
@Override
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
// 取出 sql 中的参数映射列表
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())) {
// 实参可以直接通过 TypeHandler 转换成 JdbcType
value = parameterObject;
} else {
// 获取对象中相应的属性位或查找 Map 对象中位
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
// 获取 ParameterMapping 中设置的 TypeHandler 对象
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
// 通过 TypeHandler setParameter() 方法会调用 PreparedStatement.set *() 方法,为 SQL 语句绑定相应的实参
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException | SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
}
网友评论