千家信息网

Mybatis中ResultSetHandler的用法

发表于:2025-12-03 作者:千家信息网编辑
千家信息网最后更新 2025年12月03日,本篇内容介绍了"Mybatis中ResultSetHandler的用法"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读
千家信息网最后更新 2025年12月03日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的用法"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

方法 对象 数据 属性 结果 封装 复杂 一行 内容 情况 更多 知识 过程 反射 实用 学有所成 接下来 不断 个人 个数 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 管理软件开发哪个品牌好 广东x86视频服务器 lol老是连接不了服务器 数据库唯一索引性能测试 专科生计算机网络技术和建筑工程技术哪个好 软件开发公司怎么找客户的 湖北朗涯互联网科技有限公司 数据库 邮件提醒 2013网络安全自查小结 与服务器缺少信任关系 振芯科技互联网 河南省健康码数据库查询接口 佛山安卓软件开发 数据库演示软件 广西时代网络技术分类资费 企业级地理数据库的连接文件 北京信科互联网科技有限公司 ladp服务器什么意思 信息网络安全论文简单 全面促进网络安全保护 硕士查重数据库包括哪些 方舟生存进化服务器炸了怎么解决 从excel到数据库中 启东选择网络技术排名靠前 数据库装好后换磁盘 拒做网络安全俘虏案件怎么看 威海新正网络技术有限公司好吗 吉林信息化软件开发检测中心 胡啸作《网络安全法》 c用数据库
0