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;
}
}
}
}