MyBatis执行SQL查询,并将结果映射为java对象源码分析

MyBatis执行SQL查询,比将结果映射为java对象

mybatis利用jdbc的PreparedStatement查询,是如何知道对查询结果ResultSet rs利用rs.getInt 还是用rs.getDate的呢

先从SQL查询的// RoutingStatementHandler类开始进入

@Override
public <E> List<E> query(Statement statement) throws SQLException {
    return delegate.<E>query(statement);
}

然后到

@Override
public <E> List<E> query(Statement statement) throws SQLException {
    // 这里就到了熟悉的PreparedStatement了
    PreparedStatement ps = (PreparedStatement) statement;
    // 执行SQL查询操作
    ps.execute();
    // 结果交给ResultHandler来处理
    return resultSetHandler.<E> handleResultSets(ps);
}

然后进入DefaultResultSetHandler类

public List<Object> handleResultSets(Statement stmt) throws SQLException {
        ErrorContext.instance().activity("handling results").object(this.mappedStatement.getId());
        List<Object> multipleResults = new ArrayList();
        int resultSetCount = 0;
        ResultSetWrapper rsw = this.getFirstResultSet(stmt);
        List<ResultMap> resultMaps = this.mappedStatement.getResultMaps();
        int resultMapCount = resultMaps.size();
        this.validateResultMapsCount(rsw, resultMapCount);

        while(rsw != null && resultMapCount > resultSetCount) {
            ResultMap resultMap = (ResultMap)resultMaps.get(resultSetCount);
            this.handleResultSet(rsw, resultMap, multipleResults, (ResultMapping)null);
            rsw = this.getNextResultSet(stmt);
            this.cleanUpAfterHandlingResultSet();
            ++resultSetCount;
        }

        String[] resultSets = this.mappedStatement.getResultSets();
        if (resultSets != null) {
            while(rsw != null && resultSetCount < resultSets.length) {
                ResultMapping parentMapping = (ResultMapping)this.nextResultMaps.get(resultSets[resultSetCount]);
                if (parentMapping != null) {
                    String nestedResultMapId = parentMapping.getNestedResultMapId();
                    ResultMap resultMap = this.configuration.getResultMap(nestedResultMapId);
                    this.handleResultSet(rsw, resultMap, (List)null, parentMapping);
                }

                rsw = this.getNextResultSet(stmt);
                this.cleanUpAfterHandlingResultSet();
                ++resultSetCount;
            }
        }

        return this.collapseSingleResultList(multipleResults);
    }

ResultSetWrapper是ResultSet的包装类,调用getFirstResultSet方法获取第一个ResultSet,同时获取数据库的MetaData数据,包括数据表列名、列的类型、类序号等,这些信息都存储在ResultSetWrapper类中了。然后调用handleResultSet方法来来进行结果集的封装。

private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
        try {
            if (parentMapping != null) {
                this.handleRowValues(rsw, resultMap, (ResultHandler)null, RowBounds.DEFAULT, parentMapping);
            } else if (this.resultHandler == null) {
                DefaultResultHandler defaultResultHandler = new DefaultResultHandler(this.objectFactory);
                this.handleRowValues(rsw, resultMap, defaultResultHandler, this.rowBounds, (ResultMapping)null);
                multipleResults.add(defaultResultHandler.getResultList());
            } else {
                this.handleRowValues(rsw, resultMap, this.resultHandler, this.rowBounds, (ResultMapping)null);
            }
        } finally {
            this.closeResultSet(rsw.getResultSet());
        }

    }

这里调用DefaultResultSetHandler类的handleRowValues方法来进行值的设置:

public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
        if (resultMap.hasNestedResultMaps()) {
            this.ensureNoRowBounds();
            this.checkResultHandler();
            this.handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
        } else {
            this.handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
        }

    }

然后进入

 private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
        DefaultResultContext<Object> resultContext = new DefaultResultContext();
        this.skipRows(rsw.getResultSet(), rowBounds);

        while(this.shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
            ResultMap discriminatedResultMap = this.resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, (String)null);
            Object rowValue = this.getRowValue(rsw, discriminatedResultMap);
            this.storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
        }

    }

然后进入getRowValue方法:

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
        ResultLoaderMap lazyLoader = new ResultLoaderMap();
        Object rowValue = this.createResultObject(rsw, resultMap, lazyLoader, (String)null);
        if (rowValue != null && !this.hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
            MetaObject metaObject = this.configuration.newMetaObject(rowValue);
            boolean foundValues = this.useConstructorMappings;
            if (this.shouldApplyAutomaticMappings(resultMap, false)) {
                foundValues = this.applyAutomaticMappings(rsw, resultMap, metaObject, (String)null) || foundValues;
            }

            foundValues = this.applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, (String)null) || foundValues;
            foundValues = lazyLoader.size() > 0 || foundValues;
            rowValue = !foundValues && !this.configuration.isReturnInstanceForEmptyRow() ? null : rowValue;
        }

        return rowValue;
    }
// DefaultResultSetHandler类(把ResultSet中查询结果填充到JavaBean中)
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
        List<DefaultResultSetHandler.UnMappedColumnAutoMapping> autoMapping = this.createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
        boolean foundValues = false;
        if (!autoMapping.isEmpty()) {
            Iterator var7 = autoMapping.iterator();

            while(true) {
                DefaultResultSetHandler.UnMappedColumnAutoMapping mapping;
                Object value;
                do {
                    if (!var7.hasNext()) {
                        return foundValues;
                    }

                    mapping = (DefaultResultSetHandler.UnMappedColumnAutoMapping)var7.next();
                    value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
                    if (value != null) {
                        foundValues = true;
                    }
                } while(value == null && (!this.configuration.isCallSettersOnNulls() || mapping.primitive));

                metaObject.setValue(mapping.property, value);
            }
        } else {
            return foundValues;
        }
    }
再返回getRowValue方法中执行applyPropertyMappings
private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
        List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
        boolean foundValues = false;
        List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
        Iterator var9 = propertyMappings.iterator();

        while(true) {
            while(true) {
                Object value;
                String property;
                do {
                    ResultMapping propertyMapping;
                    String column;
                    do {
                        if (!var9.hasNext()) {
                            return foundValues;
                        }

                        propertyMapping = (ResultMapping)var9.next();
                        column = this.prependPrefix(propertyMapping.getColumn(), columnPrefix);
                        if (propertyMapping.getNestedResultMapId() != null) {
                            column = null;
                        }
                    } while(!propertyMapping.isCompositeResult() && (column == null || !mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) && propertyMapping.getResultSet() == null);

                    value = this.getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
                    property = propertyMapping.getProperty();
                } while(property == null);

                if (value == DEFERED) {
                    foundValues = true;
                } else {
                    if (value != null) {
                        foundValues = true;
                    }

                    if (value != null || this.configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive()) {
                        metaObject.setValue(property, value);
                    }
                }
            }
        }
    }
然后进入getPropertyMappingValue
private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
        if (propertyMapping.getNestedQueryId() != null) {
            return this.getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);
        } else if (propertyMapping.getResultSet() != null) {
            this.addPendingChildRelation(rs, metaResultObject, propertyMapping);
            return DEFERED;
        } else {
            TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
            String column = this.prependPrefix(propertyMapping.getColumn(), columnPrefix);
            return typeHandler.getResult(rs, column);
        }
    }

在上面这个方法中:

TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();

这个会返回具体的typeHandler

然后进入到typeHandler.getResult(rs, column);
public T getResult(ResultSet rs, String columnName) throws SQLException {
        Object result;
        try {
            result = this.getNullableResult(rs, columnName);
        } catch (Exception var5) {
            throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set.  Cause: " + var5, var5);
        }

        return rs.wasNull() ? null : result;
    }

例如typeHandler为LongTypeHandler的话,那么进入到LongTypeHandler的getNullableResult:

即:

    public Long getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getLong(columnName);
    }

最后在applyPropertyMappings方法中执行metaObject.setValue(property, value);

metaValue.setValue方法最后会调用到Java类中对应数据域的set方法,这样也就完成了SQL查询结果集的Java类封装过程,过程中用到了反射。

 
原创文章 317 获赞 416 访问量 112万+

猜你喜欢

转载自blog.csdn.net/u014082714/article/details/104038856
今日推荐