Mybatis之是如何执行你的SQL的(SQL执行过程,参数解析过程,结果集封装过程)

Myabtis的SQL的执行是通过SqlSession。默认的实现类是DefalutSqlSession。通过源码可以发现,selectOne最终会调用selectList这个方法。

 1   @Override
 2   public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
 3     try {
     //获取MappedStatement 通过id 到configuration里面
4 MappedStatement ms = configuration.getMappedStatement(statement); 5 return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); 6 } catch (Exception e) { 7 throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); 8 } finally { 9 ErrorContext.instance().reset(); 10 } 11 }

通过上面可以发现是通过Executor去执行查询。但是executor是个接口,是什么时候指定的用什么执行器呢。

因为SqlSession是通过SqlSessionFactory接口获取的,实现类是DefaultSqlSessionFactory

 1   private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
 2     Transaction tx = null;
 3     try {
 4       final Environment environment = configuration.getEnvironment();
 5       final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
 6       tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
 7       final Executor executor = configuration.newExecutor(tx, execType);
 8       return new DefaultSqlSession(configuration, executor, autoCommit);
 9     } catch (Exception e) {
10       closeTransaction(tx); // may have fetched a connection so lets call close()
11       throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
12     } finally {
13       ErrorContext.instance().reset();
14     }
15   }
 1 public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
 2     executorType = executorType == null ? defaultExecutorType : executorType;
 3     executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
 4     Executor executor;
 5     if (ExecutorType.BATCH == executorType) {
 6       executor = new BatchExecutor(this, transaction);
 7     } else if (ExecutorType.REUSE == executorType) {
 8       executor = new ReuseExecutor(this, transaction);
 9     } else {
10       executor = new SimpleExecutor(this, transaction);
11     }
12     if (cacheEnabled) {
13       executor = new CachingExecutor(executor);
14     }
15     executor = (Executor) interceptorChain.pluginAll(executor);
16     return executor;
17   }

可以看到默认的是SimpleExecutor;然后默认的是开启缓存的,所以最终应该是一个CachingExecutor,但是CachingExecutor有一个构造器参数是前面的执行器。

这是一种典型的装饰器设计模式

下面那行代码你现在只需要知道如果有Executor的拦截器,就会返回一个代理对象,在执行executor方法前,会执行拦截器。这是动态代理。

后面讲Myabtis拦截器原理的时候会详细介绍。

这下知道了是CachingExecotor,来看下CachingExecutor方法;

1  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
2     BoundSql boundSql = ms.getBoundSql(parameterObject);
3     CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
4     return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
5   }

① 先看是如何获取BoundSql  这个对象,包含了sql,params等信息。

 1   public BoundSql getBoundSql(Object parameterObject) {
 2     BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
 3     List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
 4     if (parameterMappings == null || parameterMappings.isEmpty()) {
 5       boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
 6     }
 7 
 8     // check for nested result maps in parameter mappings (issue #30)
 9     for (ParameterMapping pm : boundSql.getParameterMappings()) {
10       String rmId = pm.getResultMapId();
11       if (rmId != null) {
12         ResultMap rm = configuration.getResultMap(rmId);
13         if (rm != null) {
14           hasNestedResultMaps |= rm.hasNestedResultMaps();
15         }
16       }
17     }

可以发现从sqlSource中获取BoundSql

一,DynamicSqlSourcre

 1 public class DynamicSqlSource implements SqlSource {
 2 
 3   private Configuration configuration;
 4   private SqlNode rootSqlNode;
 5 
 6   public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {
 7     this.configuration = configuration;
 8     this.rootSqlNode = rootSqlNode;
 9   }
10 
11   @Override
12   public BoundSql getBoundSql(Object parameterObject) {
这一块的操作就是替换sql里面${}部分
13 DynamicContext context = new DynamicContext(configuration, parameterObject); 14 rootSqlNode.apply(context); 15 SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration); 16 Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass(); 17 SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings()); 18 BoundSql boundSql = sqlSource.getBoundSql(parameterObject); 19 for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) { 20 boundSql.setAdditionalParameter(entry.getKey(), entry.getValue()); 21 } 22 return boundSql; 23 } 24 25 }

来看下是如何替换sql的:

 1   public DynamicContext(Configuration configuration, Object parameterObject) {
 2     if (parameterObject != null && !(parameterObject instanceof Map)) {
//如果参数类型不是map则构造一个MetaObject; //todo 这一块干嘛的目前还不清楚,后面研究mybatis反射时候研究
//这个对象 保存着Configuration的那个几个factory 反射factory 驼峰Factory,创建对象factory
3 MetaObject metaObject = configuration.newMetaObject(parameterObject); 4 bindings = new ContextMap(metaObject); 5 } else { 6 bindings = new ContextMap(null); 7 } 8 bindings.put(PARAMETER_OBJECT_KEY, parameterObject);//_paramter 9 bindings.put(DATABASE_ID_KEY, configuration.getDatabaseId()); 10 }

rootSqlNode.apply实际上接口的方法,这是根据节点的类别去执行,我们正常的MixedSqlNode实际上就是SqlNode数组类型,

这里只拿TextSqlNode做例子来看:

1   @Override
2   public boolean apply(DynamicContext context) {
3     GenericTokenParser parser = createParser(new BindingTokenParser(context, injectionFilter));
4     context.appendSql(parser.parse(text));
5     return true;
6   }

看过上一篇的应该对这段有了解, 就是用具体解析类来解析节点内容来,parser获取${}中间变量的名字,然后BindingTokenParser去处理;

parser.parses就是把sql里面每个${}替换成相应的值的作用

 1     public BindingTokenParser(DynamicContext context, Pattern injectionFilter) {
 2       this.context = context;
 3       this.injectionFilter = injectionFilter;
 4     }
 5 
 6     @Override
 7     public String handleToken(String content) {
//从参数对象里面获取值返回
8 Object parameter = context.getBindings().get("_parameter"); 9 if (parameter == null) { 10 context.getBindings().put("value", null);
//是不是基本类型
11 } else if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) { 12 context.getBindings().put("value", parameter); 13 }
//获取到对应值,这一块很复杂,有时间在研究。
14 Object value = OgnlCache.getValue(content, context.getBindings()); 15 String srtValue = (value == null ? "" : String.valueOf(value)); // issue #274 return "" instead of "null" 16 checkInjection(srtValue); 17 return srtValue; 18 } 19 20 private void checkInjection(String value) { 21 if (injectionFilter != null && !injectionFilter.matcher(value).matches()) { 22 throw new ScriptingException("Invalid input. Please conform to regex" + injectionFilter.pattern()); 23 } 24 } 25 }

好了 到此为止 sql里面${}都已经替换成该有的值了,根据变量名获取Value这一块下回研究下在另外写篇文章。

然后看这段代码:

SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);

这一段也很重要 实际上是填充boundSql里面parameterMapping的

来看SqlSourceBuilder

1   public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
2     ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
3     GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
4     String sql = parser.parse(originalSql);
5     return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
6   }

这一块代码应该很熟悉了吧, 实际上就是把#{}替换成? 同时记录下参数的类型等信息,因为逻辑前面有介绍,直接看ParameterMappingTokenHandler的方法

 1     public String handleToken(String content) {
//记录参数
2 parameterMappings.add(buildParameterMapping(content));
//替换成?
3 return "?"; 4 } 5 6 private ParameterMapping buildParameterMapping(String content) { 7 Map<String, String> propertiesMap = parseParameterMapping(content); 8 String property = propertiesMap.get("property"); 9 Class<?> propertyType; 10 if (metaParameters.hasGetter(property)) { // issue #448 get type from additional params 11 propertyType = metaParameters.getGetterType(property); 12 } else if (typeHandlerRegistry.hasTypeHandler(parameterType)) { 13 propertyType = parameterType; 14 } else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) { 15 propertyType = java.sql.ResultSet.class; 16 } else if (property != null) { 17 MetaClass metaClass = MetaClass.forClass(parameterType, configuration.getReflectorFactory()); 18 if (metaClass.hasGetter(property)) { 19 propertyType = metaClass.getGetterType(property); 20 } else { 21 propertyType = Object.class; 22 } 23 } else { 24 propertyType = Object.class; 25 } 26 ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType); 27 Class<?> javaType = propertyType;
设置每个参数类型等。
28 String typeHandlerAlias = null; 29 for (Map.Entry<String, String> entry : propertiesMap.entrySet()) { 30 String name = entry.getKey(); 31 String value = entry.getValue(); 32 if ("javaType".equals(name)) { 33 javaType = resolveClass(value); 34 builder.javaType(javaType); 35 } else if ("jdbcType".equals(name)) { 36 builder.jdbcType(resolveJdbcType(value)); 37 } else if ("mode".equals(name)) { 38 builder.mode(resolveParameterMode(value)); 39 } else if ("numericScale".equals(name)) { 40 builder.numericScale(Integer.valueOf(value)); 41 } else if ("resultMap".equals(name)) { 42 builder.resultMapId(value); 43 } else if ("typeHandler".equals(name)) { 44 typeHandlerAlias = value; 45 } else if ("jdbcTypeName".equals(name)) { 46 builder.jdbcTypeName(value); 47 } else if ("property".equals(name)) { 48 // Do Nothing 49 } else if ("expression".equals(name)) { 50 throw new BuilderException("Expression based parameters are not supported yet"); 51 } else { 52 throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content + "}. Valid properties are " + parameterProperties); 53 } 54 } 55 if (typeHandlerAlias != null) { 56 builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias)); 57 } 58 return builder.build(); 59 }

现在回过头开始看CachingExecutor的query方法了

 1   public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
 2       throws SQLException {
//这块就是mybatis的二级缓存
3 Cache cache = ms.getCache(); 4 if (cache != null) { 5 flushCacheIfRequired(ms); 6 if (ms.isUseCache() && resultHandler == null) { 7 ensureNoOutParams(ms, parameterObject, boundSql); 8 @SuppressWarnings("unchecked") 9 List<E> list = (List<E>) tcm.getObject(cache, key); 10 if (list == null) { 11 list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); 12 tcm.putObject(cache, key, list); // issue #578 and #116 13 } 14 return list; 15 } 16 }
//最终调用的还是CachingExecutor里装饰的那个执行器
17 return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); 18 }

这个方法是所有执行器父类的BaseExecutor来实现的

 1   public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
 2     ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
 3     if (closed) {
 4       throw new ExecutorException("Executor was closed.");
 5     }
 6     if (queryStack == 0 && ms.isFlushCacheRequired()) {
 7       clearLocalCache();
 8     }
 9     List<E> list;
10     try {
11       queryStack++;
12       list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
13       if (list != null) {
14         handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
15       } else {
16         list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
17       }
18     } finally {
19       queryStack--;
20     }
21     if (queryStack == 0) {
22       for (DeferredLoad deferredLoad : deferredLoads) {
23         deferredLoad.load();
24       }
25       // issue #601
26       deferredLoads.clear();
27       if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
28         // issue #482
29         clearLocalCache();
30       }
31     }
32     return list;
33   }

//这里应该就是mybatis的一级缓存,直接看从数据库查询数据

 1   private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
 2     List<E> list;
 3     localCache.putObject(key, EXECUTION_PLACEHOLDER);
 4     try {
     //在子类中实现的 doQuery 查询出来结果放入一级缓存
5 list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql); 6 } finally { 7 localCache.removeObject(key); 8 } 9 localCache.putObject(key, list); 10 if (ms.getStatementType() == StatementType.CALLABLE) { 11 localOutputParameterCache.putObject(key, parameter); 12 } 13 return list; 14 }

看SimpleExecutor的doQuery的实现

 1   public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
 2     Statement stmt = null;
 3     try {
 4       Configuration configuration = ms.getConfiguration();
//创建StatementHandler的代理对象,有的话返回代理对象,没有返回默认的RoutingStatmenthandler 典型的责任链模式
5 StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql); 6 stmt = prepareStatement(handler, ms.getStatementLog()); 7 return handler.<E>query(stmt, resultHandler); 8 } finally { 9 closeStatement(stmt); 10 } 11 }

接下来看下是怎么创建合适的Statement对象的,

1   private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
2     Statement stmt;
3     Connection connection = getConnection(statementLog);
4     stmt = handler.prepare(connection);
5     handler.parameterize(stmt);//设置参数
6     return stmt;
7   }

RoutingStatmenthandler

1 @Override
2 public Statement prepare(Connection connection) throws SQLException {
3   return delegate.prepare(connection);
4 }
5 
6 @Override
7 public void parameterize(Statement statement) throws SQLException {
8   delegate.parameterize(statement);
9 }

调用的都是装饰的statementHander ,delegate是在RoutingStatementHandler构造器初始化的;

 1  public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
 2 
 3     switch (ms.getStatementType()) {
 4       case STATEMENT:
 5         delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
 6         break;
 7       case PREPARED:
 8         delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
 9         break;
10       case CALLABLE:
11         delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
12         break;
13       default:
14         throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
15     }
16 
17   }

可以看出来是根据ms保存的,三张就是Statement的三种,我们直接看预编译的,PreparedStatementHandler

实际上一些公共方法在BaseStatementHandler实现了

 1   public Statement prepare(Connection connection) throws SQLException {
 2     ErrorContext.instance().sql(boundSql.getSql());
 3     Statement statement = null;
 4     try {
 5       statement = instantiateStatement(connection);
 6       setStatementTimeout(statement);
 7       setFetchSize(statement);
 8       return statement;
 9     } catch (SQLException e) {
10       closeStatement(statement);
11       throw e;
12     } catch (Exception e) {
13       closeStatement(statement);
14       throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
15     }
16   }

instantiateStatement子类PreparedStatementHandler实现

 1   protected Statement instantiateStatement(Connection connection) throws SQLException {
 2     String sql = boundSql.getSql();
 3     if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
 4       String[] keyColumnNames = mappedStatement.getKeyColumns();
 5       if (keyColumnNames == null) {
 6         return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
 7       } else {
 8         return connection.prepareStatement(sql, keyColumnNames);
 9       }
10     } else if (mappedStatement.getResultSetType() != null) {
11       return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
12     } else {
13       return connection.prepareStatement(sql);
14     }
15   }

上面就是根据mappedStatement的resultType不同创建不同构造器的Statement;

下面来看下参数是怎么设置的。PreparedStatementHandler,但是handler是里面的paramterHandler是什么实现类呢?什么时候注入的呢?

1   public void parameterize(Statement statement) throws SQLException {
2     parameterHandler.setParameters((PreparedStatement) statement);
3   }

来看下BaseStatementHandler的构造器

 1   protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
 2     this.configuration = mappedStatement.getConfiguration();
 3     this.executor = executor;
 4     this.mappedStatement = mappedStatement;
 5     this.rowBounds = rowBounds;
 6 
 7     this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
 8     this.objectFactory = configuration.getObjectFactory();
 9 
10     if (boundSql == null) { // issue #435, get the key before calculating the statement
11       generateKeys(parameterObject);
12       boundSql = mappedStatement.getBoundSql(parameterObject);
13     }
14 
15     this.boundSql = boundSql;
16     //都说是相当于注册参数处理器,结果集处理器了。下面看默认的参数处理器是啥
17     this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
18     this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
19   }
1   public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
//可以看出来就是从mappenStatement的语言注册器创建参数处理器。实际上就一个语言处理器。
2 ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql); 3 parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler); 4 return parameterHandler; 5 }

默认的就是XMLLanguageDriver

1 public class XMLLanguageDriver implements LanguageDriver {
2 
3   @Override
4   public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
5     return new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
6   }

接下来就看DefaultParameterHandler怎么实现setParameters()

 1   @Override
 2   public void setParameters(PreparedStatement ps) {
 3     ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
 4     List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
 5     if (parameterMappings != null) {
 6       for (int i = 0; i < parameterMappings.size(); i++) {
 7         ParameterMapping parameterMapping = parameterMappings.get(i);
 8         if (parameterMapping.getMode() != ParameterMode.OUT) {
 9           Object value;
10           String propertyName = parameterMapping.getProperty();
11           if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
12             value = boundSql.getAdditionalParameter(propertyName);
13           } else if (parameterObject == null) {
14             value = null;
15           } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
16             value = parameterObject;
17           } else {
18             MetaObject metaObject = configuration.newMetaObject(parameterObject);
19             value = metaObject.getValue(propertyName);
20           }
21           TypeHandler typeHandler = parameterMapping.getTypeHandler();
22           JdbcType jdbcType = parameterMapping.getJdbcType();
23           if (value == null && jdbcType == null) {
//这里有bug 如果传入值为0 也没设置参数jdbctype 会报错,这块可以给根据javaType给默认的类型
24 jdbcType = configuration.getJdbcTypeForNull(); 25 } 26 try { 27 typeHandler.setParameter(ps, i + 1, value, jdbcType); 28 } catch (TypeException e) { 29 throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); 30 } catch (SQLException e) { 31 throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); 32 } 33 } 34 } 35 } 36 }

这块就很简单了 根据每个参数JavaType jdbctype设设置。到此为止 prepareStatement的参数就都设置完了。

来看下 查询return handler.<E>query(stmt, resultHandler);

实际上也是PreparedStatementHandler实现的

1   @Override
2   public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
3     PreparedStatement ps = (PreparedStatement) statement;
4     ps.execute();
//执行就不说了,就看下面 使用结果处理器来处理结果集 返回一个List
5 return resultSetHandler.<E> handleResultSets(ps); 6 }

resultSetHandler在父类构造器初始化的。看下默认的是什么吧

1   public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
2       ResultHandler resultHandler, BoundSql boundSql) {
3     ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
4     resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
5     return resultSetHandler;
6   }
 1 public List<Object> handleResultSets(Statement stmt) throws SQLException {
 2     ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
 3 
 4     final List<Object> multipleResults = new ArrayList<Object>();
 5 
 6     int resultSetCount = 0;
//ResultSet的包装类ResultSet,同时获取数据库的MetaData数据,包括数据表列名、列的类型、类序号等
7 ResultSetWrapper rsw = getFirstResultSet(stmt); 8 9 List<ResultMap> resultMaps = mappedStatement.getResultMaps(); 10 int resultMapCount = resultMaps.size(); 11 validateResultMapsCount(rsw, resultMapCount); 12 while (rsw != null && resultMapCount > resultSetCount) { 13 ResultMap resultMap = resultMaps.get(resultSetCount); 14 handleResultSet(rsw, resultMap, multipleResults, null); 15 rsw = getNextResultSet(stmt); 16 cleanUpAfterHandlingResultSet(); 17 resultSetCount++; 18 } 19 20 String[] resultSets = mappedStatement.getResulSets(); 21 if (resultSets != null) { 22 while (rsw != null && resultSetCount < resultSets.length) { 23 ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); 24 if (parentMapping != null) { 25 String nestedResultMapId = parentMapping.getNestedResultMapId(); 26 ResultMap resultMap = configuration.getResultMap(nestedResultMapId); 27 handleResultSet(rsw, resultMap, null, parentMapping); 28 } 29 rsw = getNextResultSet(stmt); 30 cleanUpAfterHandlingResultSet(); 31 resultSetCount++; 32 } 33 } 34 35 return collapseSingleResultList(multipleResults); 36 }
 1   private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
 2     try {
 3       if (parentMapping != null) {
 4         handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
 5       } else {
 6         if (resultHandler == null) {
 7           DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
 8           handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
 9           multipleResults.add(defaultResultHandler.getResultList());
10         } else {
11           handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
12         }
13       }
14     } finally {
15       // issue #228 (close resultsets)
16       closeResultSet(rsw.getResultSet());
17     }
18   }
1   private void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
2     if (resultMap.hasNestedResultMaps()) {
3       ensureNoRowBounds();
4       checkResultHandler();
//嵌套结果集
5 handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping); 6 } else {
//简单的结果集
7 handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping); 8 } 9 }
 1   private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
 2       throws SQLException {
 3     DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
 4     skipRows(rsw.getResultSet(), rowBounds);
 5     while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
 6       ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
 7       Object rowValue = getRowValue(rsw, discriminatedResultMap); //获取每一行的值
 8       storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
 9     }
10   }
 1   private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
 2     final ResultLoaderMap lazyLoader = new ResultLoaderMap();
//创建数据对象的类对象 //todo这一块好复杂,有时间但单独在分析。
3 Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null); 4 if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) { 5 final MetaObject metaObject = configuration.newMetaObject(resultObject); 6 boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty(); 7 if (shouldApplyAutomaticMappings(resultMap, false)) {
//这一块就是为这个对象挨个赋值了
8 foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues; 9 } 10 foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues; 11 foundValues = lazyLoader.size() > 0 || foundValues; 12 resultObject = foundValues ? resultObject : null; 13 return resultObject; 14 } 15 return resultObject; 16 }
 1   private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
 2     List<UnMappedColumAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
 3     boolean foundValues = false;
 4     if (autoMapping.size() > 0) {
//遍历表的每一项 给对象赋值。
5 for (UnMappedColumAutoMapping mapping : autoMapping) {
//根据对应的java类型调用不同getResult获取值 如String, getString(); Int getInt()
6 final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column); 7 // issue #377, call setter on nulls 8 if (value != null || configuration.isCallSettersOnNulls()) { 9 if (value != null || !mapping.primitive) { 10 metaObject.setValue(mapping.property, value); 11 } 12 foundValues = true; 13 } 14 } 15 } 16 return foundValues; 17 }

到此为止,整个过程结束,结果集封装理解不是特别多,还有就是其中一些细节要以后慢慢推敲。如果有的地方解释的不对的地方希望看到的能及时提出探讨,万分感谢

原文地址:https://www.cnblogs.com/haoerlv/p/9936366.html