千家信息网

Mybatis中ResultSetHandler的用法

发表于:2025-01-31 作者:千家信息网编辑
千家信息网最后更新 2025年01月31日,本篇内容介绍了"Mybatis中ResultSetHandler的用法"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读
千家信息网最后更新 2025年01月31日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安全错误 数据库的锁怎样保障安全 上海疾丰网络技术有限公司 重庆专业软件开发怎么样 宜宾服务器充电桩 外包软件开发的报价 腾讯的网络安全部门 jar包数据库链接 牛客网中国移动软件开发笔试 肥东网络技术服务 爱青城服务器异常是怎么回事 数据库文件被人删除怎么办 深圳市云杰软件开发有限公司 计算机网络技术是什么系部 江西省高校网络安全技能大赛决赛 七日杀本地搭建服务器如何登录 ftp服务器显示 gps定位管理平台服务器 广东通信软件开发优化价格 银川新华互联网科技学校官网 海外华人互联网科技论坛 数据库劳资管理系统ER图 学习后端服务器需要多久技术 数据库参考文献2020 保山网络安全前景 怎样理解数据库中数据的冗余 网络安全幽默句子 服务器多个独立桌面 社区支行网络安全 普洱市网络技术中心 韩国直播软件显示服务器连接失败 数据库串行调度数量
0