mybatis源码学习之执行过程分析(5)——sql执行后ResultSet的处理及结果返回
2017-01-04 19:16
906 查看
mybatis源码学习及分析之执行过程分析(5)——返回结果的处理
上一篇中分析了sql语句的创建和执行过程,使用jdbc时,执行完sql后会返回ResultSet,然后我们会通过getInteger()、getString()等方法拿到数据。而使用Mybatis中我们可以直接将结果转换为POJO对象,下面就来看看mybatis是如何封装ResultSet的。PreparedStatementHandler.java public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; ps.execute(); //在这里开始结果处理 return resultSetHandler.<E> handleResultSets(ps); }
这里用到了ResultSetHandler。
DefaultResultSetHandler.java public List<Object> handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(mapdpedStatement.getId()); final List<Object> multipleResults = new ArrayList<Object>(); int resultSetCount = 0; //获取ResultSet并包装为ResultSetWrapper ResultSetWrapper rsw = getFirstResultSet(stmt); List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); validateResultMapsCount(rsw, resultMapCount); while (rsw != null && resultMapCount > resultSetCount) { ResultMap resultMap = resultMaps.get(resultSetCount); 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++; } } return collapseSingleResultList(multipleResults); } private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException { //JDBC中的代码,在这里拿到了ResultSet ResultSet rs = stmt.getResultSet(); while (rs == null) { // move forward to get the first resultset in case the driver // doesn't return the resultset as the first result (HSQLDB 2.1) if (stmt.getMoreResults()) { rs = stmt.getResultSet(); } else { if (stmt.getUpdateCount() == -1) { // no more results. Must be no resultset break; } } } //将ResultSet包装为ResultSetWrapper return rs != null ? new ResultSetWrapper(rs, configuration) : null; }
当前调用栈信息:
当ResultSet不为空时,也就是查到了结果,通过rs和Configuration实例化了ResultSetWrapper。
public class ResultSetWrapper { private final ResultSet resultSet; private final TypeHandlerRegistry typeHandlerRegistry; private final List<String> columnNames = new ArrayList<String>(); private final List<String> classNames = new ArrayList<String>(); private final List<JdbcType> jdbcTypes = new ArrayList<JdbcType>(); private final Map<String, Map<Class<?>, TypeHandler<?>>> typeHandlerMap = new HashMap<String, Map<Class<?>, TypeHandler<?>>>(); private Map<String, List<String>> mappedColumnNamesMap = new HashMap<String, List<String>>(); private Map<String, List<String>> unMappedColumnNamesMap = new HashMap<String, List<String>>(); public ResultSetWrapper(ResultSet rs, Configuration configuration) throws SQLException { super(); //从configuration中拿到了typeHandlerRegistry this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); this.resultSet = rs; //拿到了列信息 final int columnCount = metaData.getColumnCount(); //将每一列的名称、jdbc类型、java类型分别保存在三个ArrayList中。 for (int i = 1; i <= columnCount; i++) { columnNames.add(configuration.isUseColumnLabel() ? metaData.getColumnLabel(i) : metaData.getColumnName(i)); jdbcTypes.add(JdbcType.forCode(metaData.getColumnType(i))); classNames.add(metaData.getColumnClassName(i)); } } 。。。 }
当前调用栈如下图:
返回的ResultSetWrapper信息如图:
到这里,我们的调用栈就返回到了
DefaultResultHandler#handleResultSets(Statement stmt)。
接下来通过mappedStatement拿到了xml中配置的ResultMap。
可以看到ResultMap是我们将jdbc类型数据映射为POJO对象的重要手段。
validateResultMapsCount(rsw, resultMapCount);
对ResultMap进行校验,当查询返回的ResultMap数量小于1时,说明没有找到对应的ResultType或者ResultMap可以将结果映射出来,在这里就会抛出
ExecutorException异常。
接下来重要的操作就是
handleResultSet(rsw, resultMap, multipleResults, null);这里开始对结果集进行封装。
DefaultResultSetHandler.java private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException { try { if (parentMapping != null) { handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping); } else { if (resultHandler == null) { DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory); //处理行信息 handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null); multipleResults.add(defaultResultHandler.getResultList()); } else { //调用 handleRowValues(rsw, resultMap, resultHandler, rowBounds, null); } } } finally { // issue #228 (close resultsets) closeResultSet(rsw.getResultSet()); } } private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>(); skipRows(rsw.getResultSet(), rowBounds); while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) { ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null); //调用getRowValue Object rowValue = getRowValue(rsw, discriminatedResultMap); storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); } } private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException { final ResultLoaderMap lazyLoader = new ResultLoaderMap(); //创建了User Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null); if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { //拿到列信息 final MetaObject metaObject = configuration.newMetaObject(resultObject); boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty(); if (shouldApplyAutomaticMappings(resultMap, false)) { foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues; } foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues; foundValues = lazyLoader.size() > 0 || foundValues; resultObject = foundValues ? resultObject : null; return resultObject; } return resultObject; } //调用User的setter方法为User实例设置信息 private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix); boolean foundValues = false; final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); for (ResultMapping propertyMapping : propertyMappings) { String column = prependPrefix(propertyMapping.getColumn(), columnPrefix); if (propertyMapping.getNestedResultMapId() != null) { // the user added a column attribute to a nested result map, ignore it column = null; } if (propertyMapping.isCompositeResult() || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) || propertyMapping.getResultSet() != null) { //getPropertyMappingValue在这里对了数据转换 Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix); // issue #541 make property optional final String property = propertyMapping.getProperty(); if (property == null) { continue; } else if (value == DEFERED) { foundValues = true; continue; } if (value != null) { foundValues = true; } if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) { // gcode issue #377, call setter on nulls (value is not 'found') //在这里使用了setter方法设置值 metaObject.setValue(property, value); } } } return foundValues; }
可以看到调用了User的setName。
private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { if (propertyMapping.getNestedQueryId() != null) { return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix); } else if (propertyMapping.getResultSet() != null) { addPendingChildRelation(rs, metaResultObject, propertyMapping); // TODO is that OK? return DEFERED; } else { //typeHandler final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler(); //数据库表的列名 final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix); //得到数据库中信息 return typeHandler.getResult(rs, column); } }
当所有的值都设置完成后,已经得到了我们需要的POJO类信息,调用栈开始出栈操作,方法return。
至此,结果封装完成,所有调用栈开始出栈操作,最后返回我们需要的User。
相关文章推荐
- mybatis源码学习之执行过程分析(1)——SqlSessionFactory及SqlSession的创建
- mybatis源码学习之执行过程分析(4)——映射文件中sql的获取和sql语句的执行
- mybatis源码学习之执行过程分析(3)——mapper接口的获取
- MyBatis源码学习笔记(十)SQL执行流程分析
- Mybatis3源码分析(16)-Sql解析执行-结果集映射(ResultSetHandler)
- mybatis源码学习之执行过程分析(2)——config.xml配置文件和mapper.xml映射文件解析过程
- mybatis源码学习之执行过程分析(0)——配置文件加载(io包)
- Mybatis源码分析之Mapper执行SQL过程(三)
- Mybatis源码分析之结果封装ResultSetHandler和DefaultResultSetHandler
- Mybatis3源码分析(17)-Sql解析执行-缓存的实现
- java调用存储过程时,返回结果不是ResultSet的时候的处理
- MyBatis源码分析-SQL语句执行的完整流程
- mybatis源码分析——SqlSessionFactory实例的产生过程
- Mybatis源码分析之结果封装ResultSetHandler和DefaultResultSetHandler
- Mybatis3源码分析(13)-Sql解析执行-BoundSql的加载-2
- MySQL存错过程动态执行sql的方式来返回结果集
- spring mvc框架整个执行过程,从输入http url,到action映射,再到action处理,返回jsp文件,解析jsp文件,然后渲染, 到返回给浏览器展示结果
- Mybatis3源码分析(14)-Sql解析执行-StatementHandler
- Mybatis源码分析之结果封装ResultSetHandler和DefaultResultSetHandler
- oracle 存储过程执行可输入sql语句并返回结果集