上一篇文章中分析了插入操作的流程,这次看一下查询操作是怎么做的,获取SqlSession的过程跟插入操作一样,这里直接看查询操作的执行,入口依旧在DefaultSqlSession中:
public class DefaultSqlSession implements SqlSession {
public <E> List<E> selectList(String statement, Object parameter) {
return this.<E>selectList(statement, parameter, RowBounds.DEFAULT);
}
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
List<E> result = executor.<E>query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
return result;
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
//selectOne最终调用的也是selectList方法,然后从list重获取第一个元素。
public <T> T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
List<T> list = this.<T>selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
}
CachingExecutor:
public class CachingExecutor implements Executor {
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//获取BoundSql的过程和insert操作是一样的
BoundSql boundSql = ms.getBoundSql(parameterObject);
//创建cacheKey,根据mappedstatement的id,rowBounds以及parameterObject生成
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
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);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, key, parameterObject, boundSql);
//如果当前的缓存有效,则获取读锁,然后从缓存中获取结果。
if (!dirty) {
cache.getReadWriteLock().readLock().lock();
try {
@SuppressWarnings("unchecked")
List<E> cachedList = (List<E>) cache.getObject(key);
if (cachedList != null) return cachedList;
} finally {
cache.getReadWriteLock().readLock().unlock();
}
}
//被代理的对象执行真正的query逻辑
List<E> list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
//将结果放到缓存中
tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
return list;
}
}
return delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
}
BaseExecutor:
public abstract class BaseExecutor implements Executor {
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (closed) throw new ExecutorException("Executor was closed.");
if (queryStack == 0 && ms.isFlushCacheRequired()) {
//如果没有查询,而且当前语句需要清空缓存,则清空本地缓存
clearLocalCache();
}
List<E> list;
try {
queryStack++;
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
//如果缓存结果不为空,对于callable类型的statement,处理一下本地缓存的output。
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
//从数据库查询结果
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
if (queryStack == 0) {
//不是很理解
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
deferredLoads.clear(); // issue #601
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
clearLocalCache(); // issue #482
}
}
return list;
}
private void handleLocallyCachedOutputParameters(MappedStatement ms, CacheKey key, Object parameter, BoundSql boundSql) {
if (ms.getStatementType() == StatementType.CALLABLE) {
final Object cachedParameter = localOutputParameterCache.getObject(key);
if (cachedParameter != null && parameter != null) {
final MetaObject metaCachedParameter = configuration.newMetaObject(cachedParameter);
final MetaObject metaParameter = configuration.newMetaObject(parameter);
for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
if (parameterMapping.getMode() != ParameterMode.IN) {
final String parameterName = parameterMapping.getProperty();
final Object cachedValue = metaCachedParameter.getValue(parameterName);
metaParameter.setValue(parameterName, cachedValue);
}
}
}
}
}
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
//这个地方的作用,大概是占位???
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
//真正的执行逻辑,具体调用SimpleExecutor中的实现
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
//缓存到本地
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
//对于callable类型的语句,结果缓存到本地。
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
}
SimpleExecutor:
public class SimpleExecutor extends BaseExecutor {
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
//获取connection, StatementHandler和prepare statement的过程同insert操作一致,不多说了。
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = prepareStatement(handler, ms.getStatementLog());
//真正的query操作在PreparedStatementHandler中
return handler.<E>query(stmt, resultHandler);
} finally {
//最终关闭statement
closeStatement(stmt);
}
}
}
PreparedStatementHandler:
public class PreparedStatementHandler extends BaseStatementHandler {
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.<E> handleResultSets(ps);
}
}
FastResultSetHandler:
public class FastResultSetHandler implements ResultSetHandler {
//
// HANDLE RESULT SETS
//
public List<Object> handleResultSets(Statement stmt) throws SQLException {
final List<Object> multipleResults = new ArrayList<Object>();
final List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
int resultSetCount = 0;
ResultSet rs = stmt.getResultSet();
while (rs == null) {
// move forward to get the first resultset in case the driver
// doesn't return the resultset as the first result (HSQLDB 2.1)
if (stmt.getMoreResults()) {
rs = stmt.getResultSet();
} else {
if (stmt.getUpdateCount() == -1) {
// no more results. Must be no resultset
break;
}
}
}
validateResultMapsCount(rs, resultMapCount);
//此处这么做是为了支持sql语句的结果有多个resultSet
while (rs != null && resultMapCount > resultSetCount) {
final ResultMap resultMap = resultMaps.get(resultSetCount);
//解析resultSet中的metaDate,获取到每个结果的columnName,JDBCType以及className
ResultColumnCache resultColumnCache = new ResultColumnCache(rs.getMetaData(), configuration);
//处理resultSet
handleResultSet(rs, resultMap, multipleResults, resultColumnCache);
//获取下一个resultSet
rs = getNextResultSet(stmt);
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
return collapseSingleResultList(multipleResults);
}
protected void handleResultSet(ResultSet rs, ResultMap resultMap, List<Object> multipleResults, ResultColumnCache resultColumnCache) throws SQLException {
try {
if (resultHandler == null) {
//如果resultHandler为空,则使用默认的
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
//获取每一行的结果,并将其添加到结果集中
handleRowValues(rs, resultMap, defaultResultHandler, rowBounds, resultColumnCache);
multipleResults.add(defaultResultHandler.getResultList());
} else {
handleRowValues(rs, resultMap, resultHandler, rowBounds, resultColumnCache);
}
} finally {
closeResultSet(rs); // issue #228 (close resultsets)
}
}
protected void handleRowValues(ResultSet rs, ResultMap resultMap, ResultHandler resultHandler, RowBounds rowBounds, ResultColumnCache resultColumnCache) throws SQLException {
final DefaultResultContext resultContext = new DefaultResultContext();
//根据rowBounds,跳过部分结果
skipRows(rs, rowBounds);
//读取结果,直到读取了要求的条数,或者没有更多结果
while (shouldProcessMoreRows(rs, resultContext, rowBounds)) {
//解析DiscriminatedResultMap,即根据结果决定使用的resultMap,配置的时候形如:
//<discriminator javaType="int" column="draft">
// <case value="1" resultType="DraftPost"/>
//</discriminator>
final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rs, resultMap, null);
//获取每一行的结果
Object rowValue = getRowValue(rs, discriminatedResultMap, null, resultColumnCache);
//将结果添加到resultHandler中
callResultHandler(resultHandler, resultContext, rowValue);
}
}
//
// DISCRIMINATOR
//
public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
Set<String> pastDiscriminators = new HashSet<String>();
Discriminator discriminator = resultMap.getDiscriminator();
while (discriminator != null) {
final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);
final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value));
if (configuration.hasResultMap(discriminatedMapId)) {
resultMap = configuration.getResultMap(discriminatedMapId);
Discriminator lastDiscriminator = discriminator;
discriminator = resultMap.getDiscriminator();
if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) {
break;
}
} else {
break;
}
}
return resultMap;
}
//
// GET VALUE FROM ROW
//
protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey rowKey, ResultColumnCache resultColumnCache) throws SQLException {
//如果不允许懒加载,则lazyLoader为空
final ResultLoaderMap lazyLoader = instantiateResultLoaderMap();
//初始化返回结果对象
Object resultObject = createResultObject(rs, resultMap, lazyLoader, null, resultColumnCache);
//填充返回结果对象
if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
final MetaObject metaObject = configuration.newMetaObject(resultObject);
boolean foundValues = resultMap.getConstructorResultMappings().size() > 0;
if (shouldApplyAutomaticMappings(resultMap, !AutoMappingBehavior.NONE.equals(configuration.getAutoMappingBehavior()))) {
//获取resultSet中,那些不在resultMap中的字段
final List<String> unmappedColumnNames = resultColumnCache.getUnmappedColumnNames(resultMap, null);
//将未映射的字段的值,设置到返回结果中。如果无法设置任何一个未映射的字段,则返回结果为false。
foundValues = applyAutomaticMappings(rs, unmappedColumnNames, metaObject, null, resultColumnCache) || foundValues;
}
//获取resultSet中,所有在resultMap中的字段
final List<String> mappedColumnNames = resultColumnCache.getMappedColumnNames(resultMap, null);
//将映射的字段的值,设置到返回结果中,同时处理关联对象。果无法设置任何一个映射的字段,则返回结果为false。
foundValues = applyPropertyMappings(rs, resultMap, mappedColumnNames, metaObject, lazyLoader, null) || foundValues;
foundValues = (lazyLoader != null && lazyLoader.size() > 0) || foundValues;
resultObject = foundValues ? resultObject : null;
return resultObject;
}
return resultObject;
//至此,结果的处理就结束了。
}
//下面是一些方法的展开
//
// INSTANTIATION & CONSTRUCTOR MAPPING
//
protected Object createResultObject(ResultSet rs, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix, ResultColumnCache resultColumnCache) throws SQLException {
final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();
final List<Object> constructorArgs = new ArrayList<Object>();
//初始化返回结果对象
final Object resultObject = createResultObject(rs, resultMap, constructorArgTypes, constructorArgs, columnPrefix, resultColumnCache);
//如果懒加载,则对返回结果对象创建代理,在通过方法对关联对象进行调用的时候,加载关联对象。(不是很明白这里为什么要确保resultMap的type对应的handler不存在)
//如果非懒加载,则直接返回结果对象,在后续设置值的时候再去查询。
if (resultObject != null && configuration.isLazyLoadingEnabled() && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
for (ResultMapping propertyMapping : propertyMappings) {
if (propertyMapping.getNestedQueryId() != null) { // issue #109 (avoid creating proxies for leaf objects)
//对返回结果进行代理,这个地方仅仅是设置了代理,还没有设置在代理对象中去加载那些关联对象
return proxyFactory.createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
}
}
}
return resultObject;
}
protected boolean applyAutomaticMappings(ResultSet rs, List<String> unmappedColumnNames, MetaObject metaObject, String columnPrefix, ResultColumnCache resultColumnCache) throws SQLException {
boolean foundValues = false;
for (String columnName : unmappedColumnNames) {
String propertyName = columnName;
if (columnPrefix != null && columnPrefix.length() > 0) {
// When columnPrefix is specified,
// ignore columns without the prefix.
if (columnName.startsWith(columnPrefix)) {
propertyName = columnName.substring(columnPrefix.length());
} else {
//如果前缀不符合要求,则跳过
continue;
}
}
final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
if (property != null) {
final Class<?> propertyType = metaObject.getSetterType(property);
if (typeHandlerRegistry.hasTypeHandler(propertyType)) {
final TypeHandler<?> typeHandler = resultColumnCache.getTypeHandler(propertyType, columnName);
final Object value = typeHandler.getResult(rs, columnName);
if (value != null || configuration.isCallSettersOnNulls()) { // issue #377, call setter on nulls
metaObject.setValue(property, value);
foundValues = true;
}
}
}
}
return foundValues;
}
//
// PROPERTY MAPPINGS
//
protected boolean applyPropertyMappings(ResultSet rs, ResultMap resultMap, List<String> mappedColumnNames, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
boolean foundValues = false;
final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
for (ResultMapping propertyMapping : propertyMappings) {
final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
if (propertyMapping.isCompositeResult() || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))) {
//获取property的值
Object value = getPropertyMappingValue(rs, metaObject, propertyMapping, lazyLoader, columnPrefix);
if (value != OMIT && (value != null || configuration.isCallSettersOnNulls())) { // issue #377, call setter on nulls
final String property = propertyMapping.getProperty(); // issue #541 make property optional
if (property != null) {
metaObject.setValue(property, value);
foundValues = true;
}
}
}
}
return foundValues;
}
protected Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
if (propertyMapping.getNestedQueryId() != null) {
//如果property是一个关联属性
return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);
} else if (typeHandler != null) {
final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
return typeHandler.getResult(rs, column);
}
return OMIT;
}
protected Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
final String nestedQueryId = propertyMapping.getNestedQueryId();
final String property = propertyMapping.getProperty();
final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);
final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();
final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, propertyMapping, nestedQueryParameterType, columnPrefix);
Object value = OMIT;
if (nestedQueryParameterObject != null) {
final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);
final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);
final Class<?> targetType = propertyMapping.getJavaType();
final Object nestedQueryCacheObject = getNestedQueryCacheObject(nestedQuery, key);
if (nestedQueryCacheObject != null && nestedQueryCacheObject instanceof List) {
value = resultExtractor.extractObjectFromList((List<Object>)nestedQueryCacheObject, targetType);
} else if (executor.isCached(nestedQuery, key)) {
executor.deferLoad(nestedQuery, metaResultObject, property, key, targetType);
} else {
final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);
//如果支持懒加载,则将该关联属性的获取操作添加到lazyLoader中,这样在代理对象中可以去获取该关联属性。
if (configuration.isLazyLoadingEnabled()) {
lazyLoader.addLoader(property, metaResultObject, resultLoader);
} else {
//否则直接获取关联属性的值
value = resultLoader.loadResult();
}
}
}
return value;
}
}