SqlSession 的四大对象是指:Executor, StatementHandler,ParameterHandler,ResultHandler对象。Mybatis通过四大对象的相互协作,完成对数据库的操作。
这篇我们讲解最后的两个对象 ParameterHandler 和 ResultHandler。
1. ParameterHandler
上篇mybatis学习_SqlSession的四大对象(2)说到,在StatmentHandler中,使用了ParameterHandler帮助其完成对预编译参数的设置。
先来看看Paramrterhandler的接口定义
public interface ParameterHandler {
Object getParameterObject();
void setParameters(PreparedStatement ps)
throws SQLException;
}
非常的简洁,就两个方法,一个用来获取参数对象,一个用来设置参数。
我们重点看看设置参数方法setParameters在 其唯一的实现类 DefaultParameterHandler中的实现
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
//遍历了所有的需要设置的预编译参数。对应着xml文件中的#{}表达式
//这里仅仅只注入#{}中的参数,${}表达式代表的不是预编译参数,所以不在这里注入
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
//获取到预编译参数对应的参数值:value
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);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
//由typeHandler完成参数的设置
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);
}
}
}
}
}
梳理一下。在这个方法中会遍历所有#{}表达式所表示的预编译参数,并尝试从参数对象中获取参数对应的值。最后把这个值交给TypeHandler去注入。TypeHandler完成对jdbcType和javaType的映射后,调用parameterStatement对应的 setXXX(value)方法完成参数的设置。
2. ResultSetHandler
ResultSetHandler 的作用就是将 Statement执行返回的 resultSet映射成对应的类型。
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
final List<Object> multipleResults = new ArrayList<Object>();
int resultSetCount = 0;
//获取结果集的第一个结果
ResultSetWrapper rsw = getFirstResultSet(stmt);
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
//获取resultMap的长度,我们写的resultTye和resulrMap都会被封装成resultMap
//这个长度通常为1
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
while (rsw != null && resultMapCount > resultSetCount) {
ResultMap resultMap = resultMaps.get(resultSetCount);
//这里把结果转换成java对象
handleResultSet(rsw, resultMap, multipleResults, null);
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
//这里处理多结果集
String[] resultSets = mappedStatement.getResultSets();
if (resultSets != null) {
while (rsw != null && resultSetCount < resultSets.length) {
ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
handleResultSet(rsw, resultMap, null, parentMapping);
}
rsw = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
}
关于结果集具体的封装细节这里就不具体说了。
那么SqlSession的四大对象的功能,到这里就讲解结束了。SqlSession四大对象是mybatis插件的基础。有关于mybatis插件的讲解,会在后面更新。