如下为mybatis的一个集合查询:
String resource = "mybatis.cfg.xml"; Reader reader = Resources.getResourceAsReader(resource); SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(reader); SqlSession sqlSession = ssf.openSession(); try { List<User> users = sqlSession.selectList("User.selectUser", "1"); //查询状态为1的用户 for (User user : users) { System.out.println(user); } } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); }
- 其中SqlSession默认为DefaultSqlSession:
public class DefaultSqlSession implements SqlSession { private Configuration configuration; private Executor executor; ... ... @Override public <E> List<E> selectList(String statement) { return this.selectList(statement, null); } @Override public <E> List<E> selectList(String statement, Object parameter) { return this.selectList(statement, parameter, RowBounds.DEFAULT); //其中RowBounds.DEFAULT为new RowBounds(); } @Override public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { //MappedStatement是mybatis根据<select id="selectByExample" resultMap="ResultMap" ... />创建的映射对象 MappedStatement ms = configuration.getMappedStatement(statement); return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } ... ... }
/** * 行数限制 */ public class RowBounds { public static final int NO_ROW_OFFSET = 0; public static final int NO_ROW_LIMIT = Integer.MAX_VALUE; public static final RowBounds DEFAULT = new RowBounds(); private int offset; private int limit; public RowBounds() { this.offset = NO_ROW_OFFSET; this.limit = NO_ROW_LIMIT; } public RowBounds(int offset, int limit) { this.offset = offset; this.limit = limit; } ... ... }
- 当我们启用缓存后查询执行器Executor为CachingExector:
public class CachingExecutor implements Executor { private Executor delegate; private TransactionalCacheManager tcm = new TransactionalCacheManager(); public CachingExecutor(Executor delegate) { this.delegate = delegate;//这里的delegate为abstract class BaseExecutor implements Executor delegate.setExecutorWrapper(this); } ... ... @Override public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameterObject); CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql); return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } @Override public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { Cache cache = ms.getCache(); if (cache != null) { flushCacheIfRequired(ms);//如果<select id="selectByExample" resultMap="ResultMap" flushCache="true" ... />中设置flushCache="true",则清除缓存 if (ms.isUseCache() && resultHandler == null) { ensureNoOutParams(ms, parameterObject, boundSql);//确保查询不包括输出参数,因为缓存程序不支持输出参数 @SuppressWarnings("unchecked") List<E> list = (List<E>) tcm.getObject(cache, key);//从缓存管理器中获取缓存(缓存管理器是对各区块缓存的统一管理工具) if (list == null) { //如果从缓存中获取不到,则执行查询 list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); tcm.putObject(cache, key, list); //将查询到的结果放入缓存 } return list; } } return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } ... ... }
- CachingExecutor中的执行器代理delegate一般为ReuseExecutor:
public class ReuseExecutor extends BaseExecutor { ... ... @Override public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); Statement stmt = prepareStatement(handler, ms.getStatementLog()); return handler.<E>query(stmt, resultHandler); //执行查询 } ... ... }
- StatementHandler一般为路由StatementHandler,即RoutingStatementHandler:
public class RoutingStatementHandler implements StatementHandler { private final StatementHandler delegate; public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { /*这里的switch-case即是传说中的策略模式*/ switch (ms.getStatementType()) { case STATEMENT: delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case PREPARED: delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; case CALLABLE: delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql); break; default: throw new ExecutorException("Unknown statement type: " + ms.getStatementType()); } }
- RoutingStatementHandler其中的StatementHandler代理delegate,通常为PreparedStatementHandler;其中的query(...)方法通过调用ResultHandler的handleResultSets(...)封装查询结果:
public class PreparedStatementHandler extends BaseStatementHandler { ... ... @Override public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement) statement; ps.execute(); //执行查询 return resultSetHandler.<E> handleResultSets(ps); //处理结果集 } ... ... }
- ResultSetHandler只有一个默认结果集处理器DefaultResultSetHandler:
public interface ResultSetHandler { /** * 处理结果集 */ <E> List<E> handleResultSets(Statement stmt) throws SQLException; ... ... }
public class DefaultResultSetHandler implements ResultSetHandler { ... ... // nested resultmaps private final Map<CacheKey, Object> nestedResultObjects = new HashMap<CacheKey, Object>();//嵌套结果缓存 private final Map<CacheKey, Object> ancestorObjects = new HashMap<CacheKey, Object>();//祖对象缓存,即最外层的对象缓存 private final Map<String, String> ancestorColumnPrefix = new HashMap<String, String>(); ... ... /** * 处理所有的结果集(一次查询可能有多个语句,所以可能有多个结果集) */ @Override public List<Object> handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(mappedStatement.getId()); final List<Object> multipleResults = new ArrayList<Object>(); int resultSetCount = 0; ResultSetWrapper rsw = getFirstResultSet(stmt);//获取java.sql.ResultSet的第一个结果集(此时sql已被执行) List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); validateResultMapsCount(rsw, resultMapCount); while (rsw != null && resultMapCount > resultSetCount) { //遍历所有的结果集(一般仅一个结果集,因为通常仅一条查询语句) ResultMap resultMap = resultMaps.get(resultSetCount); handleResultSet(rsw, resultMap, multipleResults, null); //根据ResultSetWrapper和ResultMap处理结果集 rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } /*---------该方法中的以下代码暂且不做分析------------*/ String[] resultSets = mappedStatement.getResulSets(); 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); } ... ... private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException { try { if (parentMapping != null) { handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping); } else { if (resultHandler == null) {//使用结果处理器为空,则生成一个默认结果处理器 DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory); handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null); //处理记录集 multipleResults.add(defaultResultHandler.getResultList()); } else { handleRowValues(rsw, resultMap, resultHandler, rowBounds, null); //处理记录集 } } } finally { // issue #228 (close resultsets) closeResultSet(rsw.getResultSet()); } } ... ... /** * 处理所有行记录中的值 */ private void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { if (resultMap.hasNestedResultMaps()) { ensureNoRowBounds(); checkResultHandler(); handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);//嵌套映射 } else { handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);//简单映射 } } ... ... /** * 处理行值集到简单结果的映射 */ private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>(); skipRows(rsw.getResultSet(), rowBounds); while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) { ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null); Object rowValue = getRowValue(rsw, discriminatedResultMap); storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); } } ... ... /** * 处理行值集到嵌套结果的映射 */ private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { final DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>(); skipRows(rsw.getResultSet(), rowBounds); Object rowValue = null; while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) { final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null); final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null); Object partialObject = nestedResultObjects.get(rowKey);//尝试从nestedResultObjects(是HashMap<CacheKey, Object>)中获取原对象 if (mappedStatement.isResultOrdered()) { if (partialObject == null && rowValue != null) { nestedResultObjects.clear(); storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); } rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject);//获取行值 } else { rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject);//获取行值 if (partialObject == null) { storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); } } } if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) { storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); } } ... ... /** * 创建缓存的KEY(具体key的生成策略可详见文末) */ private CacheKey createRowKey(ResultMap resultMap, ResultSetWrapper rsw, String columnPrefix) throws SQLException { final CacheKey cacheKey = new CacheKey(); cacheKey.update(resultMap.getId()); List<ResultMapping> resultMappings = getResultMappingsForRowKey(resultMap); if (resultMappings.size() == 0) { if (Map.class.isAssignableFrom(resultMap.getType())) { createRowKeyForMap(rsw, cacheKey); } else { createRowKeyForUnmappedProperties(resultMap, rsw, cacheKey, columnPrefix); } } else { createRowKeyForMappedProperties(resultMap, rsw, cacheKey, resultMappings, columnPrefix); } return cacheKey; } ... ... /** * 从查询的一条行记录中获取需要映射为结果属性的值 */ private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, CacheKey absoluteKey, String columnPrefix, Object partialObject) throws SQLException { final String resultMapId = resultMap.getId(); Object resultObject = partialObject; /*如果传过来的原对象不为空,则向其中设置属性值; 否则,创建一个新结果对象作为原对象,然后设置属性值*/ if (resultObject != null) { final MetaObject metaObject = configuration.newMetaObject(resultObject); putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix); applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false); //应用嵌套映射 ancestorObjects.remove(absoluteKey); } else { final ResultLoaderMap lazyLoader = new ResultLoaderMap(); resultObject = createResultObject(rsw, resultMap, lazyLoader, columnPrefix); if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) { final MetaObject metaObject = configuration.newMetaObject(resultObject); boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty(); if (shouldApplyAutomaticMappings(resultMap, true)) { foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues; } //属性映射 foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues; putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix); //嵌套映射 foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues; ancestorObjects.remove(absoluteKey); foundValues = lazyLoader.size() > 0 || foundValues; resultObject = foundValues ? resultObject : null; } if (combinedKey != CacheKey.NULL_CACHE_KEY) { nestedResultObjects.put(combinedKey, resultObject); } } return resultObject; } ... ... /** * 应用属性映射 */ private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix); boolean foundValues = false; final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); for (ResultMapping propertyMapping : propertyMappings) { String column = prependPrefix(propertyMapping.getColumn(), columnPrefix); if (propertyMapping.getNestedResultMapId() != null) { // the user added a column attribute to a nested result map, ignore it column = null; } if (propertyMapping.isCompositeResult() || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) || propertyMapping.getResultSet() != null) { Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix); final String property = propertyMapping.getProperty(); if (value != DEFERED && property != null && (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive()))) { metaObject.setValue(property, value); } if (value != null || value == DEFERED) { foundValues = true; } } } return foundValues; } ... ... /** * 应用嵌套结果映射 */ private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) { boolean foundValues = false; //循环结果映射中所有的属性映射,如果属性为对象,即嵌套结果映射,则递归调用getRowValue(...)方法 for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) { final String nestedResultMapId = resultMapping.getNestedResultMapId(); if (nestedResultMapId != null && resultMapping.getResultSet() == null) { try { final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping); final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix); CacheKey rowKey = null; Object ancestorObject = null; if (ancestorColumnPrefix.containsKey(nestedResultMapId)) { rowKey = createRowKey(nestedResultMap, rsw, ancestorColumnPrefix.get(nestedResultMapId)); ancestorObject = ancestorObjects.get(rowKey); } if (ancestorObject != null) { if (newObject) { linkObjects(metaObject, resultMapping, ancestorObject); // issue #385 } } else { rowKey = createRowKey(nestedResultMap, rsw, columnPrefix); final CacheKey combinedKey = combineKeys(rowKey, parentRowKey); Object rowValue = nestedResultObjects.get(combinedKey); boolean knownValue = (rowValue != null); instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // mandatory if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw.getResultSet())) { //递归调用getRowValue(...)方法 rowValue = getRowValue(rsw, nestedResultMap, combinedKey, rowKey, columnPrefix, rowValue); if (rowValue != null && !knownValue) { linkObjects(metaObject, resultMapping, rowValue); foundValues = true; } } } } catch (SQLException e) { throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'. Cause: " + e, e); } } } return foundValues; } }
/** * 结果映射 */ public class ResultMap { private String id; //结果映射ID private Class<?> type; //映射结果类型 private List<ResultMapping> resultMappings; //所有内嵌的结果映射 private List<ResultMapping> idResultMappings; //所有内嵌的ID结果映射 private List<ResultMapping> constructorResultMappings; //所有构造映射 private List<ResultMapping> propertyResultMappings; //所有的属性映射 ... ... private ResultMap() { } ... ... }
- 备注:DefaultResultSetHandler中CacheKey的创建策略
<resultMap id="BaseResultMap" type="com.muwu.mjh.product.model.Cupboard" > <id column="id" property="id" jdbcType="INTEGER" /> <result column="name" property="name" jdbcType="VARCHAR" /> <result column="mark" property="mark" jdbcType="VARCHAR" /> <association property="unit" javaType="com.muwu.mjh.system.model.Unit" autoMapping="false"> <id property="id" column="unit_id"/> <result property="name" column="unit_name"/> </association> <association property="productType" javaType="com.muwu.mjh.product.model.ProductType" autoMapping="false"> <id property="id" column="product_type_id"/> <result property="name" column="product_type_name"/> <result property="parentId" column="parent_id"/> </association> <collection property="modules" ofType="com.muwu.mjh.product.model.cupboard.Module" autoMapping="false" > <id property="id" column="module_id"/> <id property="sort" column="module_sort"/> <result property="name" column="module_name"/> <result property="mark" column="module_mark"/> <collection property="components" ofType="com.muwu.mjh.product.model.cupboard.Component" autoMapping="false"> <id property="id" column="component_id"/> <result property="name" column="component_name"/> <result property="mark" column="component_mark"/> <result property="image" column="component_image"/> <result property="picture" column="component_picture"/> </collection> </collection> </resultMap>
映射时生成的缓存key依次形如:
13544163:-1571759273:com.muwu.mjh.product.mapper.CupboardMapper.
RichResultMap:id:16942
-2046111186:1023173599:com.muwu.mjh.product.mapper.CupboardMapper.
mapper_resultMap[RichResultMap]_association[unit]:unit_id:10
2024729156:2397089841:com.muwu.mjh.product.mapper.CupboardMapper.
mapper_resultMap[RichResultMap]_association[productType]:product_type_id:19
1199939766:-5622484385:com.muwu.mjh.product.mapper.CupboardMapper.
mapper_resultMap[RichResultMap]_collection[modules]:module_id:51:module_sort:0
559266669:-1005085733:com.muwu.mjh.product.mapper.CupboardMapper.
mapper_resultMap[RichResultMap]_collection[modules]_collection[components]:component_id:200
可见被<id property="..." column="..."/>标注的属性和字段值都会作为CacheKey的一部分