千家信息网

Mybatis中ResultSetHandler的用法

发表于:2024-11-13 作者:千家信息网编辑
千家信息网最后更新 2024年11月13日,本篇内容介绍了"Mybatis中ResultSetHandler的用法"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读
千家信息网最后更新 2024年11月13日Mybatis中ResultSetHandler的用法

本篇内容介绍了"Mybatis中ResultSetHandler的用法"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

mybatis-3.4.6.release.

ResultSetHandler是个接口,如List-1

List-1

public interface ResultSetHandler {  //将结果转换为List   List handleResultSets(Statement stmt) throws SQLException;  //将结果转换为游标Cursor   Cursor handleCursorResultSets(Statement stmt) throws SQLException;  void handleOutputParameters(CallableStatement cs) throws SQLException;}

实现类只有DefaultResultSetHandler,实现有点复杂,因为要考虑的情况很多。

结果封装原理

List-2

                

如List-2, 定义这样一个ResultMap后,使用ObjectFactory创建一个Person对象,

person.setId(resultSet.getInt("id"))

person.setUsername(resultSet.getString("username"))

person.setPassword(resultSet.getString("password"))

person.setFltNum(resultSet.getString("flt_num"))

不过这个转换过程在实现上很复杂,其中就用到TypeHandler。

开始之前,来看下ResultSetWrapper,如下List-3,通过ResultSet获取ResultSetMetaData来获取列的属性,遍历列,获取列名称、列类型、对应的JdbcType。

List-3

public ResultSetWrapper(ResultSet rs, Configuration configuration) throws SQLException {    super();    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();    this.resultSet = rs;    final ResultSetMetaData metaData = rs.getMetaData();    final int columnCount = metaData.getColumnCount();    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));    }}

来看DefaultResultSetHandler的handleResultSets方法,

List-4

public List handleResultSets(Statement stmt) throws SQLException {    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());    final List multipleResults = new ArrayList();    int resultSetCount = 0;    ResultSetWrapper rsw = getFirstResultSet(stmt);//1    List resultMaps = mappedStatement.getResultMaps();//2    int resultMapCount = resultMaps.size();    validateResultMapsCount(rsw, resultMapCount);//3    while (rsw != null && resultMapCount > resultSetCount) {        ResultMap resultMap = resultMaps.get(resultSetCount);//4        handleResultSet(rsw, resultMap, multipleResults, null);//5        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);}

1处通过ResultSetMetadata获取列的属性

2处获取我们定义的resultMap,如List-2

3处验证resultMap个数,如果小于1则会报错

4处获取resultMap,从List中

5处是核心,调用handleResultSet->handleRowValues->handleRowValuesForSimpleResultMap

List-5

private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler resultHandler, RowBounds rowBounds, ResultMapping parentMapping)    throws SQLException {    DefaultResultContext resultContext = new DefaultResultContext();    skipRows(rsw.getResultSet(), rowBounds);    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {        ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);        Object rowValue = getRowValue(rsw, discriminatedResultMap);//1        storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());    }}

handleRowValuesForSimpleResultMap方法中,不断调用resultSet.next()方法,会获取resultSet中的所有数据。

List-5的1处,调用getRowValue方法,该方法获取resultSet中的一行数据,并将数据封装位对象

List-6

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {    final ResultLoaderMap lazyLoader = new ResultLoaderMap();    Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);//1    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {        final MetaObject metaObject = configuration.newMetaObject(rowValue);        boolean foundValues = this.useConstructorMappings;        if (shouldApplyAutomaticMappings(resultMap, false)) {        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;//2        }        foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;        foundValues = lazyLoader.size() > 0 || foundValues;        rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;    }    return rowValue;}

List-6中1处,通过反射,创建Person对象(如List-7),之后在List-6的2处

List-7

List-8

private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {    List autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);    boolean foundValues = false;    if (!autoMapping.isEmpty()) {        for (UnMappedColumnAutoMapping mapping : autoMapping) {        final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);        if (value != null) {            foundValues = true;        }        if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {            // gcode issue #377, call setter on nulls (value is not 'found')            metaObject.setValue(mapping.property, value);        }        }    }    return foundValues;}

List-8中,createAutomaticMappings方法返还sql查询的列属性--从ResultSetWrapper中获取的,之后遍历这些列,对每一列,都调用typeHandler.getResult方法获取值,之后用metaObject.setValue,内部通过反射的方式设置值。这样createAutomaticMappings方法执行完成后,就获取了resultSet中的一行数据,且封装到对象中了。

回到List-5中,getRowValue方法返回值,storeObject方法中将值放入到List中。

描述较为泛华,建议个人阅读源码。此外,比如懒加载在ResultSetHandler中实现。

Reference

  1. https://github.com/mybatis/mybatis-3/tree/3.4.x

"Mybatis中ResultSetHandler的用法"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0