Mybatis工作机制源码分析—一次select请求处理流程

        本文从源码分析的角度分析Mybatis一次select请求处理流程。

select整体处理流程

时序图


DefaultSqlSession.selectOne工作流程

时序图


DynamicSqlSource构建BoundSql工作流程


相关源码

/** DefaultSqlSession.java */
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;
	}
}

public <E> List<E> selectList(String statement, Object parameter) {
	return this.selectList(statement, parameter, RowBounds.DEFAULT);
}

public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
	try {
		// 根据statement id获取MappedStatement
		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();
	}
}

/** CachingExecutor.java */
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
	// MappedStatement构建BoundSql,实际用DynamicSqlSource或StaticSqlSource构建BoundSql
	BoundSql boundSql = ms.getBoundSql(parameterObject);
	// 构建CacheKey
	CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
	return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

/** MappedStatement.java */
public BoundSql getBoundSql(Object parameterObject) {
	BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
	List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
	if (parameterMappings == null || parameterMappings.isEmpty()) {
		boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
	}

	// check for nested result maps in parameter mappings (issue #30)
	for (ParameterMapping pm : boundSql.getParameterMappings()) {
		String rmId = pm.getResultMapId();
		if (rmId != null) {
			ResultMap rm = configuration.getResultMap(rmId);
		if (rm != null) {
			hasNestedResultMaps |= rm.hasNestedResultMaps();
		}
	  }
	}

	return boundSql;
}

/** DynamicSqlSource.java */
// DynamicSqlSource构建BoundSql
public BoundSql getBoundSql(Object parameterObject) {
	DynamicContext context = new DynamicContext(configuration, parameterObject);
	// 根据sql语句中的<where>、<foreach>等元素,动态组建完整的sql语句
	rootSqlNode.apply(context);
	SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
	Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
	// context.getSql()获取的sql语句是完整sql语句的原始形式,包括#{}等
	// 将sql语句解析为StaticSqlSource
	SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
	// 用StaticSqlSource构建BoundSql
	BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
	// 添加metaParameter
	for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
		boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
	}
	return boundSql;
}

/** MixedSqlNode.java */
public boolean apply(DynamicContext context) {
	for (SqlNode sqlNode : contents) {
		sqlNode.apply(context);
	}
	return true;
}

/** StaticTextSqlNode.java */
public boolean apply(DynamicContext context) {
	context.appendSql(text);
	return true;
}

/** TrimSqlNode.java */
public boolean apply(DynamicContext context) {
	FilteredDynamicContext filteredDynamicContext = new FilteredDynamicContext(context);
	boolean result = contents.apply(filteredDynamicContext);
	filteredDynamicContext.applyAll();
	return result;
}

/** TrimSqlNode.FilteredDynamicContext.java */
public void appendSql(String sql) {
	sqlBuffer.append(sql);
}

public void applyAll() {
	sqlBuffer = new StringBuilder(sqlBuffer.toString().trim());
	String trimmedUppercaseSql = sqlBuffer.toString().toUpperCase(Locale.ENGLISH);
	if (trimmedUppercaseSql.length() > 0) {
		applyPrefix(sqlBuffer, trimmedUppercaseSql);
		applySuffix(sqlBuffer, trimmedUppercaseSql);
	}
	delegate.appendSql(sqlBuffer.toString());
}

/** SqlSourceBuilder.java */
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
	ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
	// 解析#{}形式的参数
	GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
	// 解析后的sql为用"?"替换#{}参数,且提取对应参数的ParameterMapping
	String sql = parser.parse(originalSql);
	// 以StaticSqlSource为解析结果
	return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}

/** BoundSql.java */
public void setAdditionalParameter(String name, Object value) {
	metaParameters.setValue(name, value);
}

/** CachingExecutor.java */
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
	return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
}

/** BaseExecutor.java */
// 创建CacheKey,用MappedStatement、parameterObject、rowBounds、boundSql影响CacheKey的hashCode
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
	if (closed) {
		throw new ExecutorException("Executor was closed.");
	}
	CacheKey cacheKey = new CacheKey();
	// cacheKey关联MappedStatement id
	cacheKey.update(ms.getId());
	// cacheKey关联rowBounds offset
	cacheKey.update(Integer.valueOf(rowBounds.getOffset()));
	// cacheKey关联Offset limit
	cacheKey.update(Integer.valueOf(rowBounds.getLimit()));
	// cacheKey关联boundSql sql
	cacheKey.update(boundSql.getSql());
	List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
	TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
	// mimic DefaultParameterHandler logic
	for (int i = 0; i < parameterMappings.size(); i++) {
		ParameterMapping parameterMapping = parameterMappings.get(i);
		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关联parameterMapping value
			cacheKey.update(value);
		}
	}
	if (configuration.getEnvironment() != null) {
		// cacheKey关联environment id
		cacheKey.update(configuration.getEnvironment().getId());
	}
	return cacheKey;
}    

/** CachingExecutor.java */
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) {
		// CachingExecutor缓存处理,MappedStatement级缓存结合TransactionalCache缓存
		flushCacheIfRequired(ms);
		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); // issue #578 and #116
			}
			return list;
		}
	}
	return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

/** BaseExecutor.java */
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) {
			// 处理本地缓存的输出参数
			handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
		} else {
			// 从Database查询
			list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
		}
	} finally {
		queryStack--;
	}
	if (queryStack == 0) {
		for (DeferredLoad deferredLoad : deferredLoads) {
			deferredLoad.load();
		}
		// issue #601
		deferredLoads.clear();
		if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
			// MappedStatement级别的缓存,则清空本地缓存
			clearLocalCache();
		}
	}
	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 {
		// 从Database查询
		list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
	} finally {
		// 清空本地之前CacheKey对应的缓存
		localCache.removeObject(key);
	}
	// 将查询结果key——list缓存到localCache
	localCache.putObject(key, list);
	if (ms.getStatementType() == StatementType.CALLABLE) {
		// 将key——parameter缓存到localOutputParameterCache
		localOutputParameterCache.putObject(key, parameter);
	}
	return list;
}

/** SimpleExecutor.java */
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
	Statement stmt = null;
	try {
		Configuration configuration = ms.getConfiguration();
		StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
		stmt = prepareStatement(handler, ms.getStatementLog());
		return handler.<E>query(stmt, resultHandler);
	} finally {
		// close Statement
		closeStatement(stmt);
	}
}

/** RoutingStatementHandler.java */
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
	return delegate.<E>query(statement, resultHandler);
}

/** PreparedStatementHandler.java */
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
	PreparedStatement ps = (PreparedStatement) statement;
	ps.execute();
	return resultSetHandler.<E> handleResultSets(ps);
}

DefaultResultSetHandler.handleResultSets工作流程

时序图


相关源码

/** DefaultResultSetHandler.java */
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);

	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);
		// 获取Next ResultSet继续处理
		rsw = getNextResultSet(stmt);
		cleanUpAfterHandlingResultSet();
		resultSetCount++;
	}

	// 处理内嵌的ResultMap
	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++;
		}
	}

	// 返回ResultSet解析结果
	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);
				// defaultResultHandler将resultList转交给multipleResults
			multipleResults.add(defaultResultHandler.getResultList());
			} else {
				handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
			}
		}
	} finally {
		// close resultsets
		closeResultSet(rsw.getResultSet());
	}
}

DefaultResultSetHandler.handleRowValues工作流程

时序图


相关源码

/** DefaultResultSetHandler.java */
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);
		// 获取row对应的记录结果对象
		Object rowValue = getRowValue(rsw, discriminatedResultMap);
		// 将结果保存到resultHandler
		storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
	}
}

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 {
		根据rowBounds offset,skipRows
		for (int i = 0; i < rowBounds.getOffset(); i++) {
			rs.next();
		}
	}
}

private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) throws SQLException {
	return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
}

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

private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
	final ResultLoaderMap lazyLoader = new ResultLoaderMap();
	// 创建ResultObject对象,未赋database获取来的值
	Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);
	if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
		final MetaObject metaObject = configuration.newMetaObject(resultObject);
		boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();
		if (shouldApplyAutomaticMappings(resultMap, false)) {
			foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
		}
		foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
		foundValues = lazyLoader.size() > 0 || foundValues;
		resultObject = foundValues ? resultObject : null;
		return resultObject;
	}
	return resultObject;
}

private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
	final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();
	final List<Object> constructorArgs = new ArrayList<Object>();

	// 创建ResultObject对象
	final Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
	if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
		final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
		for (ResultMapping propertyMapping : propertyMappings) {
			// issue gcode #109 && issue #149
			if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {
				return configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
			}
		}
	}
	return resultObject;
}

// 创建ResultObject对象
private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
  throws SQLException {
	final Class<?> resultType = resultMap.getType();
	final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);
	final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
	if (typeHandlerRegistry.hasTypeHandler(resultType)) {
		return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
	} else if (!constructorMappings.isEmpty()) {
		return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);
	} else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
		return objectFactory.create(resultType);// 实例化ResultObject
	} else if (shouldApplyAutomaticMappings(resultMap, false)) {
		return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix);
	}
	throw new ExecutorException("Do not know how to create an instance of " + resultType);
}

private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) {
	if (resultMap.getAutoMapping() != null) {
		return resultMap.getAutoMapping();
	} else {
		if (isNested) {
			return AutoMappingBehavior.FULL == configuration.getAutoMappingBehavior();
		} else {
			return AutoMappingBehavior.NONE != configuration.getAutoMappingBehavior();
		}
	}
}

private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
	final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
	boolean foundValues = false;
	for (String columnName : unmappedColumnNames) {
		String propertyName = columnName;
		if (columnPrefix != null && !columnPrefix.isEmpty()) {
			// When columnPrefix is specified,
			// ignore columns without the prefix.
			if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
				propertyName = columnName.substring(columnPrefix.length());
			} else {
				continue;
			}
		}
		final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
		if (property != null && metaObject.hasSetter(property)) {
			final Class<?> propertyType = metaObject.getSetterType(property);
			if (typeHandlerRegistry.hasTypeHandler(propertyType)) {
				// 获取propertyType、columnName对应的typeHandler
				final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);
				// 获取ResultSet根据columnName获取对应的值
				final Object value = typeHandler.getResult(rsw.getResultSet(), columnName);
				// issue #377, call setter on nulls
				if (value != null || configuration.isCallSettersOnNulls()) {
					if (value != null || !propertyType.isPrimitive()) {
						// 用metaObject设置Result Object的value
						metaObject.setValue(property, value);
					}
					foundValues = true;
				}
			}
		}
	}
	return foundValues;
}

public List<String> getUnmappedColumnNames(ResultMap resultMap, String columnPrefix) throws SQLException {
	List<String> unMappedColumnNames = unMappedColumnNamesMap.get(getMapKey(resultMap, columnPrefix));
	if (unMappedColumnNames == null) {
		loadMappedAndUnmappedColumnNames(resultMap, columnPrefix);
		unMappedColumnNames = unMappedColumnNamesMap.get(getMapKey(resultMap, columnPrefix));
	}
	return unMappedColumnNames;
}

// 获取相关table中的column names
private void loadMappedAndUnmappedColumnNames(ResultMap resultMap, String columnPrefix) throws SQLException {
	List<String> mappedColumnNames = new ArrayList<String>();
	List<String> unmappedColumnNames = new ArrayList<String>();
	final String upperColumnPrefix = columnPrefix == null ? null : columnPrefix.toUpperCase(Locale.ENGLISH);
	final Set<String> mappedColumns = prependPrefixes(resultMap.getMappedColumns(), upperColumnPrefix);
	for (String columnName : columnNames) {
		final String upperColumnName = columnName.toUpperCase(Locale.ENGLISH);
		if (mappedColumns.contains(upperColumnName)) {
			mappedColumnNames.add(upperColumnName);
		} else {
			unmappedColumnNames.add(columnName);
		}
	}
	mappedColumnNamesMap.put(getMapKey(resultMap, columnPrefix), mappedColumnNames);
	unMappedColumnNamesMap.put(getMapKey(resultMap, columnPrefix), unmappedColumnNames);
}

/** ResultSetWrapper.java */
public TypeHandler<?> getTypeHandler(Class<?> propertyType, String columnName) {
	TypeHandler<?> handler = null;
	Map<Class<?>, TypeHandler<?>> columnHandlers = typeHandlerMap.get(columnName);
	if (columnHandlers == null) {
		columnHandlers = new HashMap<Class<?>, TypeHandler<?>>();
		typeHandlerMap.put(columnName, columnHandlers);
	} else {
		handler = columnHandlers.get(propertyType);
	}
	if (handler == null) {
		handler = typeHandlerRegistry.getTypeHandler(propertyType);
		// Replicate logic of UnknownTypeHandler#resolveTypeHandler
		// See issue #59 comment 10
		if (handler == null || handler instanceof UnknownTypeHandler) {
			final int index = columnNames.indexOf(columnName);
			final JdbcType jdbcType = jdbcTypes.get(index);
			final Class<?> javaType = resolveClass(classNames.get(index));
			if (javaType != null && jdbcType != null) {
				handler = typeHandlerRegistry.getTypeHandler(javaType, jdbcType);
			} else if (javaType != null) {
				handler = typeHandlerRegistry.getTypeHandler(javaType);
			} else if (jdbcType != null) {
				handler = typeHandlerRegistry.getTypeHandler(jdbcType);
			}
		}
		if (handler == null || handler instanceof UnknownTypeHandler) {
			handler = new ObjectTypeHandler();
		}
		columnHandlers.put(propertyType, handler);
	}
	return handler;
}

/** BaseTypeHandler<T>.java */
public T getResult(ResultSet rs, String columnName) throws SQLException {
	T result;
	try {
		result = getNullableResult(rs, columnName);
	} catch (Exception e) {
		throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set.  Cause: " + e, e);
	}
	if (rs.wasNull()) {
		return null;
	} else {
		return result;
	}
}

/** StringTypeHandler.java */
public String getNullableResult(ResultSet rs, String columnName)
  throws SQLException {
	return rs.getString(columnName);
}

/** DefaultResultSetHandler.java */
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);
			// issue #541 make property optional
			final String property = propertyMapping.getProperty();
			// issue #377, call setter on nulls
			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 void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
	if (parentMapping != null) {
		linkToParents(rs, parentMapping, rowValue);
	} else {
		callResultHandler(resultHandler, resultContext, rowValue);
	}
}

private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
	resultContext.nextResultObject(rowValue);
	((ResultHandler<Object>)resultHandler).handleResult(resultContext);
}

/** DefaultResultHandler.java */
public void handleResult(ResultContext<? extends Object> context) {
	list.add(context.getResultObject());
}

/** DefaultResultSetHandler.java */
private List<Object> collapseSingleResultList(List<Object> multipleResults) {
	return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值