mybatis - ResultSetHandler

本文深入解析Mybatis中的ResultSetHandler、ResultSetWrapper和DefaultResultHandler,探讨了如何处理Sql结果集、类型处理器注册以及逻辑分页技巧。重点剖析CacheKey的构成,包括Mapper ID、偏移量、限制条件和SQL信息,以及与SqlSessionFactoryBean的关联。
摘要由CSDN通过智能技术生成

mybatis - ResultSetHandler

ResultSetWrapper

private final ResultSet resultSet;
private final TypeHandlerRegistry typeHandlerRegistry;
private final List<String> columnNames = new ArrayList<>();
private final List<String> classNames = new ArrayList<>();
private final List<JdbcType> jdbcTypes = new ArrayList<>();
private final Map<String, Map<Class<?>, TypeHandler<?>>> typeHandlerMap = new HashMap<>();
private final Map<String, List<String>> mappedColumnNamesMap = new HashMap<>();
private final Map<String, List<String>> unMappedColumnNamesMap = new HashMap<>();
  • Sql结果集引用
  • 类型处理器引用

DefaultResultHandler

结果映射处理完成的引用,获取最终结果列表

DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
// 处理每一行数据
handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
multipleResults.add(defaultResultHandler.getResultList());

MappedStatement

ObjectFactory

用于创建对象

  <T> T create(Class<T> type);

CacheKey

public CacheKey() {
    this.hashcode = DEFAULT_HASHCODE;
    this.multiplier = DEFAULT_MULTIPLIER;
    this.count = 0;
    this.updateList = new ArrayList<>();
}

// BaseExecutor.java
@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
    if (closed) {
        throw new ExecutorException("Executor was closed.");
    }
    CacheKey cacheKey = new CacheKey();
    cacheKey.update(ms.getId());
    cacheKey.update(rowBounds.getOffset());
    cacheKey.update(rowBounds.getLimit());
    cacheKey.update(boundSql.getSql());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
    // mimic DefaultParameterHandler logic
    for (ParameterMapping parameterMapping : parameterMappings) {
        if (parameterMapping.getMode() != ParameterMode.OUT) {
            Object value;
            String propertyName = parameterMapping.getProperty();
            if (boundSql.hasAdditionalParameter(propertyName)) {
                value = boundSql.getAdditionalParameter(propertyName);
            } else if (parameterObject == null) {
                value = null;
            } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                value = parameterObject;
            } else {
                MetaObject metaObject = configuration.newMetaObject(parameterObject);
                value = metaObject.getValue(propertyName);
            }
            cacheKey.update(value);
        }
    }
    if (configuration.getEnvironment() != null) {
        // issue #176
        cacheKey.update(configuration.getEnvironment().getId());
    }
    return cacheKey;
}

可以发现 cacheKey 组成:

  • mapperStatementId
  • offset
  • limit
  • sql
  • sql 参数
  • configuration.getEnvironment().getId() ?? SqlSessionFactoryBean

495450185:1623395656:com.bootmybatis.dao.AccountDao.selectByPrimaryKey:0:2147483647:select id, user_name, passwd from t_accountwhere id = ?:1:SqlSessionFactoryBean

请添加图片描述

ResultLoaderMap

ProxyFactory

MetaObject

操作对象属性工具类, 最终调用 Invoker 中的 invoke 方法,使用反射对属性设值

public class MetaObject {
  //源对象
  private final Object originalObject;
  //对象属性设置
  private final ObjectWrapper objectWrapper;
  //对象创建工厂
  private final ObjectFactory objectFactory;
  //ObjectWrapper 创建工厂
  private final ObjectWrapperFactory objectWrapperFactory;
  // 类加载工厂
  private final ReflectorFactory reflectorFactory;
}

逻辑分页

mybatis 默认使用逻辑分页

private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap,
                                               ResultHandler<?> resultHandler,
                                               RowBounds rowBounds, ResultMapping parentMapping)
    throws SQLException {
    DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
    ResultSet resultSet = rsw.getResultSet();
    //对结果集分页
    skipRows(resultSet, rowBounds);
    while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
        ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
        Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
        storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
    }
}

//分页
private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
    if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
        if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {
            rs.absolute(rowBounds.getOffset());
        }
    } else {
        for (int i = 0; i < rowBounds.getOffset(); i++) {
            if (!rs.next()) {
                break;
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值