大纲:
当使用 PreparedStatetment 或者 CallableStatetment对象执行 SQL 时,如果 SQL 语句中有参数占位符,在执行 SQL 语句前就需要将占位符替换为真实值.
ParameterHandler参数处理器的作用是在PreparedStatetmentHandler 或者 CallableStatetmentHandler操作对应的 Statement 执行数据库交互之前为参数占位符设置值
public interface ParameterHandler {
Object getParameterObject();
/**
* 用于为 JDBC PreparedStatetment 或者 CallableStatetment对象 的参数占位符设置值
* @param ps
*/
void setParameters(PreparedStatement ps) throws SQLException;
}public class DefaultParameterHandler implements ParameterHandler {
private final TypeHandlerRegistry typeHandlerRegistry;
private final MappedStatement mappedStatement;
private final Object parameterObject;
private final BoundSql boundSql;
private final Configuration configuration;
@Override
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
//1 获取所有参数映射信息
List 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;
//2 参数属性名称
String propertyName = parameterMapping.getProperty();
/**
* 1 计算参数值的优先级是 先判断是不是属于语句的AdditionalParameter;
* 2 其次参数是不是null;
* 3 然后判断是不是属于注册类型;都不是,
* 4 那估计参数一定是object或者map了,这就要借助于反射工具类MetaObject获取属性值了;
*/
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 {
//4 通过configuration对象提供的工厂方法创建反射工具类 MetaObject对象,通过反射获取属性值
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
//3 获取参数对应 TypeHandler 类型处理器
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
// 4 委托具体的类型处理器进行参数的设置, 经过 BaseTypeHandler=>再到IntegerTypeHandler 执行 ps.setXX()
// jdbc下标从1开始,对于每个jdbcType, mybatis都提供了一个对应的Handler,具体可参考上文TypeHandler详解, 其内部调用的是PrepareStatement.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);
}
}
}
}
}
}
| 留言与评论(共有 0 条评论) “” |