如下为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的一部分