/*
ResultSets = [ // 《批量结果集列表》,要数据库支持
ResultSet : [ // 记录列表
Result {id:1, name:"name_1",pwd:"pwd_1"}, // 一行记录
Result {id:2, name:"name_2",pwd:"pwd_2"},
Result {id:3, name:"name_3",pwd:"pwd_3"}
],
ResultSet :[
Result {id:1, name:"name_1",pwd:"pwd_1"},
Result {id:2, name:"name_2",pwd:"pwd_2"},
Result {id:3, name:"name_3",pwd:"pwd_3"}
]
]
*/
// 0、获取文件输入流
InputStream inputStream = Resources.getResourceAsStream("foo-config.xml");
// org.apache.ibatis.scripting.defaults.RawLanguageDriver
/*
1、解析 xml 文件,设置配置到 Configuration 对象
解析mapper
1、解析《xml类型》的mapper
2、解析《注解类型》的mapper
if(类的类型是接口类型)
{
1、尝试加载 "com/test/bean/XxxMapper.xml"文件,如果存在就进行解析
2、解析类上的 @CacheNamespace 注解,创建Cache对象,并设置cache到currentCache
3、解析类上的 @CacheNamespaceRef 注解,获取Cache对象,并设置cache到currentCache
4、迭代方法
for (Method method : methods)
{
1、解析方法的参数类型 ParamMap、自定义类 FooBean、简单类型 Integer
2、解析方法上的 @Lang 注解,如果没有配置获取全局默认的值。如 org.apache.ibatis.scripting.defaults.RawLanguageDriver,org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
3、创建SqlSource对象,解析方法上的《@Select..》和 《@SelectProvider..》的注解;两种类型不能同时存在
1、@Select、@Insert、@Update、@Delete 注解
1、获取注解的值(多值用 "," 连接)
2、用 StringBuilder 拼接注解值
3、创建SqlSource对象 --- 使用 @Lang 配置的 Driver
如 RawLanguageDriver
org.apache.ibatis.scripting.defaults.RawLanguageDriver.createSqlSource(configuration对象,sql字符串,参数类型)
{
1、SqlSource source = XMLLanguageDriver.createSqlSource(configuration, script, parameterType);
{
// ...
}
2、检查 source 是否是 RawSqlSource 的实例,否则抛异常
}
如 XMLLanguageDriver
org.apache.ibatis.scripting.defaults.XMLLanguageDriver.createSqlSource(configuration对象,sql字符串,参数类型)
{
1、以<script>开头
。。。解析xml节点 。。。
2、不以<script>开头
1、用配置的变量 configuration.getVariables() 替换第一层 ${...}
2、如果还存在${...} ,那么创建DynamicSqlSource对象并返回
3、如果不存在${...} ,那么创建RawSqlSource对象并返回
1、解析 #{...},用 "?" 替换,
2、注册 占位符 到 parameterMappings,执行的时候走bindParams
}
2、@SelectProvider、@InsertProvider、@UpdateProvider、@DeleteProvider 注解
1、创建 ProviderSqlSource 对象
4、解析方法上的 @Options 注解
{
0、生成语句ID final String mappedStatementId = type.getName() + "." + method.getName();
1、获取命令类型 SqlCommandType sqlCommandType = getSqlCommandType(method)
2、获取键生成器
if(INSERT、UPDATE类型的命令)
{
if(获取@SelectKey注解配置)
{
keyGenerator = handleSelectKeyAnnotation(selectKey, mappedStatementId, getParameterType(method), languageDriver);
{
1、获取@SelectKey配置的 返回值类型、语句类型、语句、键的名称
2、生成语句ID type.getName() + "." + method.getName() + "!selectKey"
3、字段的关系
// 获取keyColumn的值,设置到目标sql的keyProperty属性中
String keyProperty = selectKeyAnnotation.keyProperty(); // 目标sql的属性名
String keyColumn = selectKeyAnnotation.keyColumn(); // 获取属性值的列名,数量与keyProperty相同
4、创建 MappedStatement,并添加到 configuration
configuration.addMappedStatement(statement);
5、添加key生成器
SelectKeyGenerator answer = new SelectKeyGenerator(keyStatement, executeBefore);
configuration.addKeyGenerator(id, answer);
}
keyProperty = selectKey.keyProperty();
}
else if (没有配置 @Options)
{
keyGenerator = configuration.isUseGeneratedKeys() ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
}
else (有配置 @Options)
{
keyGenerator = options.useGeneratedKeys() ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
keyProperty = options.keyProperty();
keyColumn = options.keyColumn();
}
}
else
{
keyGenerator = new NoKeyGenerator();
}
3、有配置 @Options
1、获取缓存配置
2、获取批量获取数量配置
3、获取超时配置
4、语句类型 StatementType.PREPARED
5、返回集类型 ResultSetType.FORWARD_ONLY
}
5、处理返回值类型
{
if(方法上有 @ResultMap 注解)
{
// @ResultMap(value={"resultMap1","resultMap2"})
resultMapId = sb.toString();
}
else(没有注解 @ResultMap 并且是 查询)
{
1、获取返回值类型
2、解析方法上的 @ConstructorArgs 注解
3、解析方法上的 @Results 注解
4、解析方法上的 @TypeDiscriminator 注解
5、生成 resultMapId
if(解析方法上有 @Results 注解,并设置了id)
{
return type.getName() + "." + results.id();
}
else
{
if(方法有参数)
{
suffix = "-" + "参数名用-拼接"
}
else
{
suffix = "-void"
}
return type.getName() + "." + method.getName() + suffix;
}
6、应用
1、迭代Arg注解,创建ResultMapping,添加到resultMappings
2、迭代Result注解,创建ResultMapping,添加到resultMappings
3、解析TypeDiscriminator注解,创建ResultMapping,创建Discriminator对象包装
4、添加到configuration
// resultMapId == "cn.java.mapper.FooMapper.method1-param0-param1"
// !!! 创建对象ResultMap,添加到configuration
assistant.addResultMap(resultMapId, returnType, null, disc, resultMappings, null);
5、迭代@TypeDiscriminator注解的@case属性
for (Case c : discriminator.cases())
{
// resultMapId == "cn.java.mapper.FooMapper.method1-param0-param1"
String caseResultMapId = resultMapId + "-" + c.value();
List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
applyConstructorArgs(c.constructArgs(), resultType, resultMappings);
applyResults(c.results(), resultType, resultMappings);
// caseResultMapId === "cn.java.mapper.FooMapper.method1-param0-param1-" + c.value()
// !!! 创建对象ResultMap,添加到configuration
assistant.addResultMap(caseResultMapId, c.type(), resultMapId, null, resultMappings, null);
}
}
}
}
5、构建 MappedStatement 对象
mappedStatement
{
....
sqlSource : sqlSource,
parameterMap : ...,
resultMaps : ...,
...
}
。。。
}
2、创建 DefaultSqlSessionFactory 对象
*/
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
/*
1、创建《事务对象》JdbcTransaction
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
2、创建《执行器》
Executor executor = configuration.newExecutor(tx, execType)
{
1、创建执行器
executor = new SimpleExecutor(this, transaction);
2、用 CachingExecutor 代理 SimpleExecutor ------- 用于缓存控制
if (cacheEnabled) { // 允许缓存
executor = new CachingExecutor(executor);
}
3、安装插件
executor = (Executor) interceptorChain.pluginAll(executor); // 安装《拦截器》,返回代理对象 ---- 用于执行executor的时候拦截
{
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target); // 返回被代理的对象
{
return Plugin.wrap(target, this);
{
1、解析拦截器类上的 @Intercepts、@Signature 注解,识别要拦截的目标方法,创建特征map
2、创建代理对象返回
}
}
}
return target;
}
}
3、创建 DefaultSqlSession
{
return new DefaultSqlSession(configuration, executor, autoCommit);
}
*/
// 自动提交的方式打开 DefaultSqlSession,会创建一个Transaction对象跟随
SqlSession sqlSession = sqlSessionFactory.openSession(true); // 打开连接(会从“数据源”中获取一个,如果没有会“创建一个”)
{
List<Foo> fooList = sqlSession.selectList("cn.java.demo.mybatis.mapper.FooTwoNonInterfaceHaveXmlNonAnnotationMapper.selectListReturnListInXml", 1);
for (Iterator iterator = fooList.iterator(); iterator.hasNext(); ) {
Foo foo = (Foo) iterator.next();
System.out.println(foo);
/*
1、获取 MappedStatement
MappedStatement ms = configuration.getMappedStatement(statement);
2、执行
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); // 执行目标方法
{
1、递归调用拦截器链条
for(拦截器列表) --------- 应用拦截器 --- 要执行executor的时候拦截
{
// ....
}
2、执行目标 executor
1、执行缓存 CachingExecutor
Cache cache = ms.getCache(); // 由类上的 @CacheNamespace 或者 @CacheNamespaceRef 控制
if (cache != null) { // 如果有配置外部缓存依赖,如 Redis
flushCacheIfRequired(ms); // 刷新外部缓存,如Redis
if (ms.isUseCache() && resultHandler == null) { // 使用外部缓存,如Redis,方法上的注解 @Options(useCache=true)
ensureNoOutParams(ms, parameterObject, boundSql);
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key); // 从外部缓存获取数据,如Redis
if (list == null) {
list = delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); // ------- 执行目标 Executor
tcm.putObject(cache, key, list); // issue #578 and #116 数据放入外部缓存,如Redis
}
return list;
}
}
// delegate === org.apache.ibatis.executor.SimpleExecutor
return delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); // ------- 执行目标 Executor
2、执行目标 Executor
// 当配置执行器类型为:ExecutorType.BATCH
org.apache.ibatis.executor.BatchExecutor.query()
{
}
// 当配置执行器类型为:ExecutorType.REUSE
org.apache.ibatis.executor.ReuseExecutor.query()
{
}
// 否则
org.apache.ibatis.executor.SimpleExecutor.query()
{
1、解析SQL,替换#{}为占位符 ?、解析绑定参数
{
BoundSql boundSql = ms.getBoundSql(parameter);
{
// parameterObject 实际调用时传递进来的参数
// sqlSource === org.apache.ibatis.scripting.defaults.RawSqlSource !!! ----- @Select("select * from table1 where field1 = #{field1_property} AND field2 = #{field2_property,:JdbcType.VARCHAR,javaType=java.lang.String,mode=ParameterMode.IN,numericScale=2,resultMap=resultMapId,typeHandler=typeHandlerAlias,jdbcTypeName=jdbcTypeName}")
// sqlSource === org.apache.ibatis.scripting.xmltags.DynamicSqlSource !!! ----- @Select("select * from table1 where field1 = ${parampre\\${param_middle\\}paramafter}")
BoundSql boundSql = sqlSource.getBoundSql(parameterObject); // 构建sql
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(); // 结果映射id
if (rmId != null) {
ResultMap rm = configuration.getResultMap(rmId);
if (rm != null) {
hasNestedResultMaps |= rm.hasNestedResultMaps();
}
}
}
return boundSql;
}
}
2、创建缓存key
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
3、执行查询
return query(ms, parameter, rowBounds, resultHandler, key, boundSql); // 查询
1、如果配置缓存、清除本地缓存
if (queryStack == 0 && ms.isFlushCacheRequired()) { // 需要缓存
clearLocalCache(); // 清除本地缓存
{
if (!closed) {
localCache.clear();
localOutputParameterCache.clear();
}
}
}
2、获取数据
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; // 尝试从本地缓存获取
if (list != null) { // 本地缓存存在数据
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); // 从本地缓存获取数据,设置到 parameter
} else { // 从数据库获取
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); // 从数据库获取!!!
{
1、查询数据
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
{
1、获取配置
Configuration configuration = ms.getConfiguration();
2、创建语句处理器
// handler == org.apache.ibatis.executor.statement.RoutingStatementHandler
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
{
1、创建RoutingStatementHandler对象
// parameterObject 实际调用时传递进来的参数
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
{
switch (ms.getStatementType()) {
case STATEMENT: // delegate(ms.getStatementType()=="STATEMENT")
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
case PREPARED: // delegate(ms.getStatementType()=="PREPARED")
// !!! 创建 PreparedStatementHandler 对象
delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
{
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds; // RowBounds.DEFAULT 对翻页的限制
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
// 生成sql语句
if (boundSql == null) {
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject); // !!!
}
this.boundSql = boundSql;
// 创建参数处理器
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
{
1、创建 ParameterHandler 对象
// org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
2、安装插件 --- 用于赋值参数的时候拦截
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler); // org.apache.ibatis.scripting.defaults.DefaultParameterHandler
}
// 创建结果集处理器
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
{
1、创建 ResultSetHandler r对象
ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
2、安装插件 --- 用于处理结果的时候拦截
resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
}
}
break;
case CALLABLE: // delegate(ms.getStatementType()=="CALLABLE")
delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
break;
default:
throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
}
}
2、安装插件
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
}
3、预处理语句
stmt = prepareStatement(handler, ms.getStatementLog());
{
Statement stmt;
Connection connection = getConnection(statementLog);
{
1、加载数据库驱动、创建连接、设置事务自动提交和隔离级别
2、用PooledConnection包装连接
3、创建PooledConnection的代理对象并返回
}
stmt = handler.prepare(connection, transaction.getTimeout()); // handler == org.apache.ibatis.executor.statement.RoutingStatementHandler
{
1、递归调用拦截器链条
for(拦截器列表) --------- 应用拦截器 --- 要执行sql的时候拦截 -- 拦截 StatementHandler
{
// ....
}
2、调用目标方法
org.apache.ibatis.executor.statement.PreparedStatementHandler.prepare(...)
{
1、初始化语句
statement = instantiateStatement(connection);
{
// 1、获取sql
String sql = boundSql.getSql();
// 2、预编译sql
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS); // 默认:插入后返回主键
} else {
return connection.prepareStatement(sql, keyColumnNames); // keyColumnNames:插入后必须返回的字段
}
} else if (mappedStatement.getResultSetType() != null) {
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
} else { // 预置语句
return connection.prepareStatement(sql); // sql = "select * from table1 where field1 = ?"
}
}
2、设置超时时间
setStatementTimeout(statement, transactionTimeout);
{
Integer queryTimeout = null;
if (mappedStatement.getTimeout() != null) {
queryTimeout = mappedStatement.getTimeout(); // 注解上配置的超时时间
} else if (configuration.getDefaultStatementTimeout() != null) {
queryTimeout = configuration.getDefaultStatementTimeout(); // 默认超时时间
}
if (queryTimeout != null) {
stmt.setQueryTimeout(queryTimeout);
}
StatementUtil.applyTransactionTimeout(stmt, queryTimeout, transactionTimeout);
}
3、设置获取数量
setFetchSize(statement);
{
Integer fetchSize = mappedStatement.getFetchSize(); // 注解上配置的获取数量
if (fetchSize != null) {
stmt.setFetchSize(fetchSize);
return;
}
Integer defaultFetchSize = configuration.getDefaultFetchSize(); // 默认获取数量
if (defaultFetchSize != null) {
stmt.setFetchSize(defaultFetchSize);
}
}
return statement;
}
}
2、绑定参数
handler.parameterize(stmt); // 赋值参数
{
0、递归调用拦截器链条
for(拦截器列表) --------- 应用拦截器 --- 要执行sql的时候拦截 -- 拦截 StatementHandler
{
// ....
}
1、拦截器执行完成,执行目标 DefaultParameterHandler
org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(PreparedStatement stmt)
{
0、递归调用拦截器链条
for(拦截器列表) --------- 应用拦截器(参数绑定的时候拦截) -- 拦截 ParameterHandler
{
// ....
}
1、执行目标代码
for (int i = 0; i < parameterMappings.size(); i++)
{
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
1、获取绑定值
String propertyName = parameterMapping.getProperty(); // 属性名 foo.account
MetaObject metaObject = configuration.newMetaObject(parameterObject); // 其他类型
value = metaObject.getValue(propertyName);
2、获取类型转换器
TypeHandler typeHandler = parameterMapping.getTypeHandler(); // 属性的类型处理器
JdbcType jdbcType = parameterMapping.getJdbcType(); // 数据库的类型 org.apache.ibatis.type.JdbcType.VARCHAR
3、转换类型,并设置值
typeHandler.setParameter(ps, i + 1, value, jdbcType); // org.apache.ibatis.type.StringTypeHandler
}
}
}
}
return stmt;
}
3、执行查询
return handler.<E>query(stmt, resultHandler);
{
PreparedStatement ps = (PreparedStatement) statement;
1、执行语句
ps.execute(); // 执行SQL语句
2、处理结果集
return resultSetHandler.<E>handleResultSets(ps);
{
1、拦截器执行完成,执行目标 DefaultResultSetHandler
org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(PreparedStatement ps)
{
0、递归调用拦截器链条
for(拦截器列表) --------- 应用拦截器(处理返回结果的时候拦截) -- 拦截 ResultSetHandler
{
// ....
}
1、获取第一个结果集ResultSet,并用ResultSetWrapper包装
ResultSetWrapper rsw = getFirstResultSet(stmt);
2、获取配置的映射
List<ResultMap> resultMaps = mappedStatement.getResultMaps(); // (通过注解 @ResultMap("resultMap1,resultMap2")得到 或者 “解析返回参数并内建” 得到 或者 解析注解@ConstructorArgs、@Results、@TypeDiscriminator)
int resultMapCount = resultMaps.size(); // 配置的“结果集定义”的数量
validateResultMapsCount(rsw, resultMapCount); // resultMaps数量必须大于0
3、填充结果数据
while (rsw != null && resultMapCount > resultSetCount) { // “结果集定义”的数量 大于 “数据库返回的结果集”数量(即:数据库的某个结果集有配置映射信息)
ResultMap resultMap = resultMaps.get(resultSetCount); // 第N个结果集映射器 org.apache.ibatis.mapping.ResultMap / ResultMap 描述的是某一行数据怎么映射的信息
handleResultSet(rsw, resultMap, multipleResults, null); // 处理结果集 --------处理结果集(即:行列表)
{
if (resultHandler == null) { // 在方法上没有定义 ResultHandler 对象
DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);// !!! ---------------debug
{
if (resultMap.hasNestedResultMaps()) { // 有嵌套
ensureNoRowBounds();
checkResultHandler();
handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
} else { // !!!
handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping); // -------------
{
DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
skipRows(rsw.getResultSet(), rowBounds); // 根据rowBounds的配置,跳过N行
{
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++) {
rs.next();
}
}
}
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) { // ------------- 迭代所有行
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null); // org.apache.ibatis.mapping.ResultMap
Object rowValue = getRowValue(rsw, discriminatedResultMap); // 获取某行数据 !!!------
{
1、创建Entity对象
Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null); // !!! 创建行或者结果对象 FooOneEntity
2、填充数据到Entity对象
if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) { // 没有类型处理器
final MetaObject metaObject = configuration.newMetaObject(resultObject);
boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty(); // 有构造函数映射
if (shouldApplyAutomaticMappings(resultMap, false)) { // 自动映射
foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues; // 应用映射---- metaObject.setValue(mapping.property, value); // 设置值
}
foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues; // 应用属性值
{
final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); // 属性映射列表
for (ResultMapping propertyMapping : propertyMappings) {
Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix); // 获取数据库返回的列值
metaObject.setValue(property, value); // 设置值
}
return foundValues;
}
foundValues = lazyLoader.size() > 0 || foundValues;
resultObject = foundValues ? resultObject : null;
return resultObject;
}
}
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet()); // ...
{
resultContext.nextResultObject(rowValue);
{
resultCount++;
this.resultObject = resultObject;
}
((ResultHandler<Object>) resultHandler).handleResult(resultContext);
{
org.apache.ibatis.executor.result.DefaultResultHandler.handleResult()
{
list.add(context.getResultObject());
}
}
}
} // EDN while
}
}
}
multipleResults.add(defaultResultHandler.getResultList(){
return list; // 返回列表
});
} else {
handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
}
}
rsw = getNextResultSet(stmt); // 获取下一个结果集
cleanUpAfterHandlingResultSet();
resultSetCount++;
}
4、处理父级别的mapping
String[] resultSets = mappedStatement.getResultSets(); // !!!!------- 通过注解 @Options(resultSets="resultSets1")得到 ,多结果集的支持
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++;
}
}
5、返回结果集合
return collapseSingleResultList(multipleResults); // 返回一个结果集
{
return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;
}
}
}
}
}
2、数据放入本地缓存
localCache.putObject(key, list); // 数据本地缓存
}
}
3、清除本地缓存
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
clearLocalCache(); // 清除本地缓存
{
if (!closed) {
localCache.clear();
localOutputParameterCache.clear();
}
}
}
}
}
*/
}
}
sqlSession.close(); // 断开连接(会断开从“数据源”获取的连接,实际上是把连接“放回数据源连接池”中)