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