ResultSetHandler负责处理两件事:
(1)处理Statement执行后产生的结果集,生成结果列表
(2)处理存储过程执行后的输出参数
ResultSetHandler是一个接口,提供了两个函数分别用来处理普通操作和存储过程的结果,
源码如下:
  1. /**
  2. * @author Clinton Begin
  3. */
  4. public interface ResultSetHandler {
  5.  
  6. <E> List<E> handleResultSets(Statement stmt) throws SQLException;
  7.  
  8. void handleOutputParameters(CallableStatement cs) throws SQLException;
  9.  
  10. }

ResultSetHandler的具体实现类是DefaultResultSetHandler,其实现的步骤就是将Statement执行后的结果集,按照Mapper文件中配置的ResultType或ResultMap来封装成对应的对象,最后将封装的对象返回即可,
DefaultResultSetHandler源码如下:

  1. //ResultSetHandler具体实现类
  2. public class DefaultResultSetHandler implements ResultSetHandler {
  3.  
  4. private static final Object DEFERED = new Object();
  5.  
  6. private final Executor executor;
  7. private final Configuration configuration;
  8. private final MappedStatement mappedStatement;
  9. private final RowBounds rowBounds;
  10. private final ParameterHandler parameterHandler;
  11. private final ResultHandler<?> resultHandler;
  12. private final BoundSql boundSql;
  13. private final TypeHandlerRegistry typeHandlerRegistry;
  14. private final ObjectFactory objectFactory;
  15. private final ReflectorFactory reflectorFactory;
  16.  
  17. // nested resultmaps
  18. // 此Map用来保存当前层级内部的结果对象(一对多关系的多方对象),key为combinedKey
  19. private final Map<CacheKey, Object> nestedResultObjects = new HashMap<CacheKey, Object>();
  20. // 此Map用来保存当前层级的根对象(一对多关系中的一方对象),key为absoluteKey
  21. private final Map<CacheKey, Object> ancestorObjects = new HashMap<CacheKey, Object>();
  22. private final Map<String, String> ancestorColumnPrefix = new HashMap<String, String>();
  23.  
  24. // multiple resultsets
  25. private final Map<String, ResultMapping> nextResultMaps = new HashMap<String, ResultMapping>();
  26. private final Map<CacheKey, List<PendingRelation>> pendingRelations = new HashMap<CacheKey, List<PendingRelation>>();
  27.  
  28. private static class PendingRelation {
  29. public MetaObject metaObject;
  30. public ResultMapping propertyMapping;
  31. }
  32.  
  33. public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler<?> resultHandler, BoundSql boundSql,
  34. RowBounds rowBounds) {
  35. this.executor = executor;
  36. this.configuration = mappedStatement.getConfiguration();
  37. this.mappedStatement = mappedStatement;
  38. this.rowBounds = rowBounds;
  39. this.parameterHandler = parameterHandler;
  40. this.boundSql = boundSql;
  41. this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
  42. this.objectFactory = configuration.getObjectFactory();
  43. this.reflectorFactory = configuration.getReflectorFactory();
  44. this.resultHandler = resultHandler;
  45. }
  46.  
  47. //
  48. // HANDLE OUTPUT PARAMETER
  49. //
  50. //调用存储过程返回结果,将结果值放在参数中
  51. @Override
  52. public void handleOutputParameters(CallableStatement cs) throws SQLException {
  53. final Object parameterObject = parameterHandler.getParameterObject();
  54. final MetaObject metaParam = configuration.newMetaObject(parameterObject);
  55. final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
  56. //循环处理每个参数
  57. for (int i = 0; i < parameterMappings.size(); i++) {
  58. final ParameterMapping parameterMapping = parameterMappings.get(i);
  59. //判断参数的模式
  60. if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {
  61. if (ResultSet.class.equals(parameterMapping.getJavaType())) {
  62. handleRefCursorOutputParameter((ResultSet) cs.getObject(i + 1), parameterMapping, metaParam);
  63. } else {
  64. final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler();
  65. metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1));
  66. }
  67. }
  68. }
  69. }
  70.  
  71. private void handleRefCursorOutputParameter(ResultSet rs, ParameterMapping parameterMapping, MetaObject metaParam) throws SQLException {
  72. try {
  73. final String resultMapId = parameterMapping.getResultMapId();
  74. final ResultMap resultMap = configuration.getResultMap(resultMapId);
  75. final DefaultResultHandler resultHandler = new DefaultResultHandler(objectFactory);
  76. final ResultSetWrapper rsw = new ResultSetWrapper(rs, configuration);
  77. handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null);
  78. metaParam.setValue(parameterMapping.getProperty(), resultHandler.getResultList());
  79. } finally {
  80. // issue #228 (close resultsets)
  81. closeResultSet(rs);
  82. }
  83. }
  84.  
  85. //
  86. // HANDLE RESULT SETS
  87. //
  88. //对普通查询到的结果转换
  89. @Override
  90. public List<Object> handleResultSets(Statement stmt) throws SQLException {
  91. ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
  92.  
  93. final List<Object> multipleResults = new ArrayList<Object>();
  94.  
  95. int resultSetCount = 0;
  96. //获取第一个结果值
  97. ResultSetWrapper rsw = getFirstResultSet(stmt);
  98. //获得resultMap
  99. List<ResultMap> resultMaps = mappedStatement.getResultMaps();
  100. //这边应该为1吧,一般resultMap为一个
  101. int resultMapCount = resultMaps.size();
  102. //判断是否有resultMap,没有的话抛出异常
  103. validateResultMapsCount(rsw, resultMapCount);
  104. while (rsw != null && resultMapCount > resultSetCount) {
  105. //获得resultMap,实体类和表中数据字段的对应关系
  106. ResultMap resultMap = resultMaps.get(resultSetCount);
  107. //将值设置成对应的resultmap对象
  108. handleResultSet(rsw, resultMap, multipleResults, null);
  109. rsw = getNextResultSet(stmt);
  110. cleanUpAfterHandlingResultSet();
  111. resultSetCount++;
  112. }
  113.  
  114. String[] resultSets = mappedStatement.getResulSets();
  115. if (resultSets != null) {
  116. while (rsw != null && resultSetCount < resultSets.length) {
  117. ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
  118. if (parentMapping != null) {
  119. String nestedResultMapId = parentMapping.getNestedResultMapId();
  120. ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
  121. handleResultSet(rsw, resultMap, null, parentMapping);
  122. }
  123. rsw = getNextResultSet(stmt);
  124. cleanUpAfterHandlingResultSet();
  125. resultSetCount++;
  126. }
  127. }
  128.  
  129. return collapseSingleResultList(multipleResults);
  130. }
  131. //获得第一个值,并将值打包
  132. private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
  133. ResultSet rs = stmt.getResultSet();
  134. //结果集不为空
  135. while (rs == null) {
  136. // move forward to get the first resultset in case the driver
  137. // doesn't return the resultset as the first result (HSQLDB 2.1)
  138. if (stmt.getMoreResults()) {
  139. rs = stmt.getResultSet();
  140. } else {
  141. if (stmt.getUpdateCount() == -1) {
  142. // no more results. Must be no resultset
  143. break;
  144. }
  145. }
  146. }
  147. //将数据打包
  148. return rs != null ? new ResultSetWrapper(rs, configuration) : null;
  149. }
  150. //获取下一个值,将值打包
  151. private ResultSetWrapper getNextResultSet(Statement stmt) throws SQLException {
  152. // Making this method tolerant of bad JDBC drivers
  153. try {
  154. if (stmt.getConnection().getMetaData().supportsMultipleResultSets()) {
  155. // Crazy Standard JDBC way of determining if there are more results
  156. if (!((!stmt.getMoreResults()) && (stmt.getUpdateCount() == -1))) {
  157. ResultSet rs = stmt.getResultSet();
  158. return rs != null ? new ResultSetWrapper(rs, configuration) : null;
  159. }
  160. }
  161. } catch (Exception e) {
  162. // Intentionally ignored.
  163. }
  164. return null;
  165. }
  166. //关闭resultSet
  167. private void closeResultSet(ResultSet rs) {
  168. try {
  169. if (rs != null) {
  170. rs.close();
  171. }
  172. } catch (SQLException e) {
  173. // ignore
  174. }
  175. }
  176.  
  177. private void cleanUpAfterHandlingResultSet() {
  178. nestedResultObjects.clear();
  179. ancestorColumnPrefix.clear();
  180. }
  181.  
  182. //校验结果的resultMap,如果没有的话就抛出异常
  183. private void validateResultMapsCount(ResultSetWrapper rsw, int resultMapCount) {
  184. if (rsw != null && resultMapCount < 1) {
  185. throw new ExecutorException("A query was run and no Result Maps were found for the Mapped Statement '" + mappedStatement.getId()
  186. + "'. It's likely that neither a Result Type nor a Result Map was specified.");
  187. }
  188. }
  189.  
  190. private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
  191. try {
  192. if (parentMapping != null) {
  193. handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
  194. } else {
  195. if (resultHandler == null) {
  196. // 创建一个新对象
  197. DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
  198. //将查询到的每个字段和Bean实体中的属性对应起来,生成一个Result对象
  199. handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
  200. //结果映射对象及值添加到multipleResults中
  201. multipleResults.add(defaultResultHandler.getResultList());
  202. } else {
  203. handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
  204. }
  205. }
  206. } finally {
  207. // issue #228 (close resultsets)
  208. closeResultSet(rsw.getResultSet());
  209. }
  210. }
  211.  
  212. @SuppressWarnings("unchecked")
  213. private List<Object> collapseSingleResultList(List<Object> multipleResults) {
  214. return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;
  215. }
  216.  
  217. //
  218. // HANDLE ROWS FOR SIMPLE RESULTMAP
  219. //
  220. //操作列值
  221. private void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
  222. if (resultMap.hasNestedResultMaps()) {
  223. ensureNoRowBounds();
  224. checkResultHandler();
  225. handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  226. } else {
  227. handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
  228. }
  229. }
  230. //判断记录行数
  231. private void ensureNoRowBounds() {
  232. if (configuration.isSafeRowBoundsEnabled() && rowBounds != null && (rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT || rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET)) {
  233. throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely constrained by RowBounds. "
  234. + "Use safeRowBoundsEnabled=false setting to bypass this check.");
  235. }
  236. }
  237.  
  238. protected void checkResultHandler() {
  239. if (resultHandler != null && configuration.isSafeResultHandlerEnabled() && !mappedStatement.isResultOrdered()) {
  240. throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely used with a custom ResultHandler. "
  241. + "Use safeResultHandlerEnabled=false setting to bypass this check "
  242. + "or ensure your statement returns ordered data and set resultOrdered=true on it.");
  243. }
  244. }
  245.  
  246. private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
  247. throws SQLException {
  248. DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
  249. //跳过RowBounds设置的offset值
  250. skipRows(rsw.getResultSet(), rowBounds);
  251. //判断数据是否小于limit,如果小于limit的话就不断的循环取值
  252. while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
  253. ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
  254. Object rowValue = getRowValue(rsw, discriminatedResultMap);
  255. storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
  256. }
  257. }
  258.  
  259. private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
  260. if (parentMapping != null) {
  261. linkToParents(rs, parentMapping, rowValue);
  262. } else {
  263. callResultHandler(resultHandler, resultContext, rowValue);
  264. }
  265. }
  266.  
  267. @SuppressWarnings("unchecked" /* because ResultHandler<?> is always ResultHandler<Object>*/)
  268. private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {
  269. resultContext.nextResultObject(rowValue);
  270. ((ResultHandler<Object>)resultHandler).handleResult(resultContext);
  271. }
  272.  
  273. private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) throws SQLException {
  274. //判断数据是否小于limit,小于返回true
  275. return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
  276. }
  277. //跳过不需要的行,应该就是rowbounds设置的limit和offset
  278. private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
  279. if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
  280. if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {
  281. rs.absolute(rowBounds.getOffset());
  282. }
  283. } else {
  284. //跳过RowBounds中设置的offset条数据
  285. for (int i = 0; i < rowBounds.getOffset(); i++) {
  286. rs.next();
  287. }
  288. }
  289. }
  290.  
  291. //
  292. // GET VALUE FROM ROW FOR SIMPLE RESULT MAP
  293. //
  294.  
  295. private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
  296. final ResultLoaderMap lazyLoader = new ResultLoaderMap();
  297. //结果的映射对象
  298. Object resultObject = createResultObject(rsw, resultMap, lazyLoader, null);
  299. if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
  300. final MetaObject metaObject = configuration.newMetaObject(resultObject);
  301. boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();
  302. if (shouldApplyAutomaticMappings(resultMap, false)) {
  303. foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
  304. }
  305. foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
  306. foundValues = lazyLoader.size() > 0 || foundValues;
  307. resultObject = foundValues ? resultObject : null;
  308. return resultObject;
  309. }
  310. return resultObject;
  311. }
  312. //用于判断是否是bean实体变量和表中字段自动映射
  313. private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) {
  314. if (resultMap.getAutoMapping() != null) {
  315. return resultMap.getAutoMapping();
  316. } else {
  317. if (isNested) {
  318. return AutoMappingBehavior.FULL == configuration.getAutoMappingBehavior();
  319. } else {
  320. return AutoMappingBehavior.NONE != configuration.getAutoMappingBehavior();
  321. }
  322. }
  323. }
  324.  
  325. //
  326. // PROPERTY MAPPINGS
  327. //
  328.  
  329. private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)
  330. throws SQLException {
  331. final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
  332. boolean foundValues = false;
  333. final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
  334. for (ResultMapping propertyMapping : propertyMappings) {
  335. String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
  336. if (propertyMapping.getNestedResultMapId() != null) {
  337. // the user added a column attribute to a nested result map, ignore it
  338. column = null;
  339. }
  340. if (propertyMapping.isCompositeResult()
  341. || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))
  342. || propertyMapping.getResultSet() != null) {
  343. Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);
  344. // issue #541 make property optional
  345. final String property = propertyMapping.getProperty();
  346. // issue #377, call setter on nulls
  347. if (value != DEFERED
  348. && property != null
  349. && (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive()))) {
  350. metaObject.setValue(property, value);
  351. }
  352. if (value != null || value == DEFERED) {
  353. foundValues = true;
  354. }
  355. }
  356. }
  357. return foundValues;
  358. }
  359.  
  360. private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)
  361. throws SQLException {
  362. if (propertyMapping.getNestedQueryId() != null) {
  363. return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);
  364. } else if (propertyMapping.getResultSet() != null) {
  365. addPendingChildRelation(rs, metaResultObject, propertyMapping); // TODO is that OK?
  366. return DEFERED;
  367. } else {
  368. final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
  369. final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
  370. return typeHandler.getResult(rs, column);
  371. }
  372. }
  373. //
  374. private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
  375. final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
  376. boolean foundValues = false;
  377. //获得列名
  378. for (String columnName : unmappedColumnNames) {
  379. String propertyName = columnName;
  380. if (columnPrefix != null && !columnPrefix.isEmpty()) {
  381. // When columnPrefix is specified,
  382. // ignore columns without the prefix.
  383. if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
  384. propertyName = columnName.substring(columnPrefix.length());
  385. } else {
  386. continue;
  387. }
  388. }
  389. final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
  390. if (property != null && metaObject.hasSetter(property)) {
  391. final Class<?> propertyType = metaObject.getSetterType(property);
  392. if (typeHandlerRegistry.hasTypeHandler(propertyType)) {
  393. final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);
  394. final Object value = typeHandler.getResult(rsw.getResultSet(), columnName);
  395. // issue #377, call setter on nulls
  396. if (value != null || configuration.isCallSettersOnNulls()) {
  397. if (value != null || !propertyType.isPrimitive()) {
  398. metaObject.setValue(property, value);
  399. }
  400. foundValues = true;
  401. }
  402. }
  403. }
  404. }
  405. return foundValues;
  406. }
  407.  
  408. // MULTIPLE RESULT SETS
  409.  
  410. private void linkToParents(ResultSet rs, ResultMapping parentMapping, Object rowValue) throws SQLException {
  411. CacheKey parentKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getForeignColumn());
  412. List<PendingRelation> parents = pendingRelations.get(parentKey);
  413. if (parents != null) {
  414. for (PendingRelation parent : parents) {
  415. if (parent != null && rowValue != null) {
  416. linkObjects(parent.metaObject, parent.propertyMapping, rowValue);
  417. }
  418. }
  419. }
  420. }
  421.  
  422. private void addPendingChildRelation(ResultSet rs, MetaObject metaResultObject, ResultMapping parentMapping) throws SQLException {
  423. CacheKey cacheKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getColumn());
  424. PendingRelation deferLoad = new PendingRelation();
  425. deferLoad.metaObject = metaResultObject;
  426. deferLoad.propertyMapping = parentMapping;
  427. List<PendingRelation> relations = pendingRelations.get(cacheKey);
  428. // issue #255
  429. if (relations == null) {
  430. relations = new ArrayList<DefaultResultSetHandler.PendingRelation>();
  431. pendingRelations.put(cacheKey, relations);
  432. }
  433. relations.add(deferLoad);
  434. ResultMapping previous = nextResultMaps.get(parentMapping.getResultSet());
  435. if (previous == null) {
  436. nextResultMaps.put(parentMapping.getResultSet(), parentMapping);
  437. } else {
  438. if (!previous.equals(parentMapping)) {
  439. throw new ExecutorException("Two different properties are mapped to the same resultSet");
  440. }
  441. }
  442. }
  443.  
  444. private CacheKey createKeyForMultipleResults(ResultSet rs, ResultMapping resultMapping, String names, String columns) throws SQLException {
  445. CacheKey cacheKey = new CacheKey();
  446. cacheKey.update(resultMapping);
  447. if (columns != null && names != null) {
  448. String[] columnsArray = columns.split(",");
  449. String[] namesArray = names.split(",");
  450. for (int i = 0 ; i < columnsArray.length ; i++) {
  451. Object value = rs.getString(columnsArray[i]);
  452. if (value != null) {
  453. cacheKey.update(namesArray[i]);
  454. cacheKey.update(value);
  455. }
  456. }
  457. }
  458. return cacheKey;
  459. }
  460.  
  461. //
  462. // INSTANTIATION & CONSTRUCTOR MAPPING
  463. //
  464. //创建结果对象
  465. private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
  466. final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();
  467. final List<Object> constructorArgs = new ArrayList<Object>();
  468. //结果对象
  469. final Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
  470. if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
  471. //获取配置的resultMap的字段与表中数据的映射关系
  472. final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
  473. for (ResultMapping propertyMapping : propertyMappings) {
  474. // issue gcode #109 && issue #149
  475. if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {
  476. return configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);
  477. }
  478. }
  479. }
  480. return resultObject;
  481. }
  482. //创建结果对象
  483. private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
  484. throws SQLException {
  485. //结果类型
  486. final Class<?> resultType = resultMap.getType();
  487. //通过反射获取结果对象
  488. final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);
  489. final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
  490. if (typeHandlerRegistry.hasTypeHandler(resultType)) {
  491. //基本类型
  492. return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
  493. } else if (!constructorMappings.isEmpty()) {
  494. //有参数构造函数
  495. return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);
  496. } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
  497. //普通的bean类型
  498. return objectFactory.create(resultType);
  499. } else if (shouldApplyAutomaticMappings(resultMap, false)) {
  500. //自动映射
  501. return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix);
  502. }
  503. throw new ExecutorException("Do not know how to create an instance of " + resultType);
  504. }
  505. //有参数构造函数
  506. Object createParameterizedResultObject(ResultSetWrapper rsw, Class<?> resultType, List<ResultMapping> constructorMappings,
  507. List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix) {
  508. boolean foundValues = false;
  509. for (ResultMapping constructorMapping : constructorMappings) {
  510. final Class<?> parameterType = constructorMapping.getJavaType();
  511. final String column = constructorMapping.getColumn();
  512. final Object value;
  513. try {
  514. if (constructorMapping.getNestedQueryId() != null) {
  515. value = getNestedQueryConstructorValue(rsw.getResultSet(), constructorMapping, columnPrefix);
  516. } else if (constructorMapping.getNestedResultMapId() != null) {
  517. final ResultMap resultMap = configuration.getResultMap(constructorMapping.getNestedResultMapId());
  518. value = getRowValue(rsw, resultMap);
  519. } else {
  520. final TypeHandler<?> typeHandler = constructorMapping.getTypeHandler();
  521. value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(column, columnPrefix));
  522. }
  523. } catch (ResultMapException e) {
  524. throw new ExecutorException("Could not process result for mapping: " + constructorMapping, e);
  525. } catch (SQLException e) {
  526. throw new ExecutorException("Could not process result for mapping: " + constructorMapping, e);
  527. }
  528. constructorArgTypes.add(parameterType);
  529. constructorArgs.add(value);
  530. foundValues = value != null || foundValues;
  531. }
  532. return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;
  533. }
  534. //自动映射
  535. private Object createByConstructorSignature(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs,
  536. String columnPrefix) throws SQLException {
  537. for (Constructor<?> constructor : resultType.getDeclaredConstructors()) {
  538. if (typeNames(constructor.getParameterTypes()).equals(rsw.getClassNames())) {
  539. boolean foundValues = false;
  540. for (int i = 0; i < constructor.getParameterTypes().length; i++) {
  541. Class<?> parameterType = constructor.getParameterTypes()[i];
  542. String columnName = rsw.getColumnNames().get(i);
  543. TypeHandler<?> typeHandler = rsw.getTypeHandler(parameterType, columnName);
  544. Object value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(columnName, columnPrefix));
  545. constructorArgTypes.add(parameterType);
  546. constructorArgs.add(value);
  547. foundValues = value != null || foundValues;
  548. }
  549. return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;
  550. }
  551. }
  552. throw new ExecutorException("No constructor found in " + resultType.getName() + " matching " + rsw.getClassNames());
  553. }
  554.  
  555. private List<String> typeNames(Class<?>[] parameterTypes) {
  556. List<String> names = new ArrayList<String>();
  557. for (Class<?> type : parameterTypes) {
  558. names.add(type.getName());
  559. }
  560. return names;
  561. }
  562. //创建原型结果
  563. private Object createPrimitiveResultObject(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
  564. final Class<?> resultType = resultMap.getType();
  565. final String columnName;
  566. if (!resultMap.getResultMappings().isEmpty()) {
  567. final List<ResultMapping> resultMappingList = resultMap.getResultMappings();
  568. final ResultMapping mapping = resultMappingList.get(0);
  569. columnName = prependPrefix(mapping.getColumn(), columnPrefix);
  570. } else {
  571. columnName = rsw.getColumnNames().get(0);
  572. }
  573. final TypeHandler<?> typeHandler = rsw.getTypeHandler(resultType, columnName);
  574. return typeHandler.getResult(rsw.getResultSet(), columnName);
  575. }
  576.  
  577. //
  578. // NESTED QUERY
  579. //
  580.  
  581. private Object getNestedQueryConstructorValue(ResultSet rs, ResultMapping constructorMapping, String columnPrefix) throws SQLException {
  582. final String nestedQueryId = constructorMapping.getNestedQueryId();
  583. final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);
  584. final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();
  585. final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, constructorMapping, nestedQueryParameterType, columnPrefix);
  586. Object value = null;
  587. if (nestedQueryParameterObject != null) {
  588. final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);
  589. final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);
  590. final Class<?> targetType = constructorMapping.getJavaType();
  591. final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);
  592. value = resultLoader.loadResult();
  593. }
  594. return value;
  595. }
  596. //得到嵌套查询值
  597. private Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)
  598. throws SQLException {
  599. final String nestedQueryId = propertyMapping.getNestedQueryId();
  600. final String property = propertyMapping.getProperty();
  601. final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);
  602. final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();
  603. final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, propertyMapping, nestedQueryParameterType, columnPrefix);
  604. Object value = null;
  605. if (nestedQueryParameterObject != null) {
  606. final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);
  607. final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);
  608. final Class<?> targetType = propertyMapping.getJavaType();
  609. if (executor.isCached(nestedQuery, key)) {
  610. //如果已经有一级缓存了,则延迟加载(实际上deferLoad方法中可以看到则是立即加载)
  611. executor.deferLoad(nestedQuery, metaResultObject, property, key, targetType);
  612. value = DEFERED;
  613. } else {
  614. //否则lazyLoader.addLoader 需要延迟加载则addLoader
  615. //或者ResultLoader.loadResult 不需要延迟加载则立即加载
  616. final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);
  617. if (propertyMapping.isLazy()) {
  618. lazyLoader.addLoader(property, metaResultObject, resultLoader);
  619. value = DEFERED;
  620. } else {
  621. value = resultLoader.loadResult();
  622. }
  623. }
  624. }
  625. return value;
  626. }
  627.  
  628. private Object prepareParameterForNestedQuery(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {
  629. if (resultMapping.isCompositeResult()) {
  630. return prepareCompositeKeyParameter(rs, resultMapping, parameterType, columnPrefix);
  631. } else {
  632. return prepareSimpleKeyParameter(rs, resultMapping, parameterType, columnPrefix);
  633. }
  634. }
  635.  
  636. private Object prepareSimpleKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {
  637. final TypeHandler<?> typeHandler;
  638. if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
  639. typeHandler = typeHandlerRegistry.getTypeHandler(parameterType);
  640. } else {
  641. typeHandler = typeHandlerRegistry.getUnknownTypeHandler();
  642. }
  643. return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));
  644. }
  645.  
  646. private Object prepareCompositeKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException {
  647. final Object parameterObject = instantiateParameterObject(parameterType);
  648. final MetaObject metaObject = configuration.newMetaObject(parameterObject);
  649. boolean foundValues = false;
  650. for (ResultMapping innerResultMapping : resultMapping.getComposites()) {
  651. final Class<?> propType = metaObject.getSetterType(innerResultMapping.getProperty());
  652. final TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(propType);
  653. final Object propValue = typeHandler.getResult(rs, prependPrefix(innerResultMapping.getColumn(), columnPrefix));
  654. // issue #353 & #560 do not execute nested query if key is null
  655. if (propValue != null) {
  656. metaObject.setValue(innerResultMapping.getProperty(), propValue);
  657. foundValues = true;
  658. }
  659. }
  660. return foundValues ? parameterObject : null;
  661. }
  662.  
  663. private Object instantiateParameterObject(Class<?> parameterType) {
  664. if (parameterType == null) {
  665. return new HashMap<Object, Object>();
  666. } else {
  667. return objectFactory.create(parameterType);
  668. }
  669. }
  670.  
  671. //
  672. // DISCRIMINATOR
  673. //
  674. public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
  675. Set<String> pastDiscriminators = new HashSet<String>();
  676. Discriminator discriminator = resultMap.getDiscriminator();
  677. while (discriminator != null) {
  678. final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);
  679. final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value));
  680. if (configuration.hasResultMap(discriminatedMapId)) {
  681. resultMap = configuration.getResultMap(discriminatedMapId);
  682. Discriminator lastDiscriminator = discriminator;
  683. discriminator = resultMap.getDiscriminator();
  684. if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) {
  685. break;
  686. }
  687. } else {
  688. break;
  689. }
  690. }
  691. return resultMap;
  692. }
  693.  
  694. private Object getDiscriminatorValue(ResultSet rs, Discriminator discriminator, String columnPrefix) throws SQLException {
  695. final ResultMapping resultMapping = discriminator.getResultMapping();
  696. final TypeHandler<?> typeHandler = resultMapping.getTypeHandler();
  697. return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));
  698. }
  699.  
  700. private String prependPrefix(String columnName, String prefix) {
  701. if (columnName == null || columnName.length() == 0 || prefix == null || prefix.length() == 0) {
  702. return columnName;
  703. }
  704. return prefix + columnName;
  705. }
  706.  
  707. //
  708. // HANDLE NESTED RESULT MAPS
  709. //
  710. //生成嵌套对象值
  711. private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
  712. //创建默认结果上下文
  713. final DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
  714. //跳过rowBounds指定offset行偏移量
  715. skipRows(rsw.getResultSet(), rowBounds);
  716. Object rowValue = null;
  717. //如何定义应该处理:上下文没有主动停止,结果集还有记录,且上下文中结果对象数量不足时,应该继续处理
  718. while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
  719. // 解决鉴别过的结果映射,逻辑如下:
  720. // 获取结果映射中的鉴别器,通过鉴别指定字段通过配置对象获取对应的另一个结果映射,循环往复,
  721. // 直到找不到鉴别器为止,返回最终的结果映射
  722. final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
  723. // 创建缓存key,如何创建?
  724. final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
  725. // 缓存中获取结果对象
  726. Object partialObject = nestedResultObjects.get(rowKey);
  727. // issue #577 && #542
  728. if (mappedStatement.isResultOrdered()) {
  729. if (partialObject == null && rowValue != null) {
  730. nestedResultObjects.clear();
  731. // 保存结果对象
  732. storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
  733. }
  734. // 获取行值
  735. rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject);
  736. } else {
  737. rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, rowKey, null, partialObject);
  738. if (partialObject == null) {
  739. storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
  740. }
  741. }
  742. }
  743. if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
  744. storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
  745. }
  746. }
  747.  
  748. //
  749. // GET VALUE FROM ROW FOR NESTED RESULT MAP
  750. //
  751. //
  752. private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, CacheKey absoluteKey, String columnPrefix, Object partialObject) throws SQLException {
  753. final String resultMapId = resultMap.getId();
  754. Object resultObject = partialObject;
  755. if (resultObject != null) {
  756. final MetaObject metaObject = configuration.newMetaObject(resultObject);
  757. putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix);
  758. applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false);
  759. ancestorObjects.remove(absoluteKey);
  760. } else {
  761. final ResultLoaderMap lazyLoader = new ResultLoaderMap();
  762. resultObject = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
  763. if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
  764. final MetaObject metaObject = configuration.newMetaObject(resultObject);
  765. boolean foundValues = !resultMap.getConstructorResultMappings().isEmpty();
  766. if (shouldApplyAutomaticMappings(resultMap, true)) {
  767. foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
  768. }
  769. foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
  770. putAncestor(absoluteKey, resultObject, resultMapId, columnPrefix);
  771. foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues;
  772. ancestorObjects.remove(absoluteKey);
  773. foundValues = lazyLoader.size() > 0 || foundValues;
  774. resultObject = foundValues ? resultObject : null;
  775. }
  776. if (combinedKey != CacheKey.NULL_CACHE_KEY) {
  777. nestedResultObjects.put(combinedKey, resultObject);
  778. }
  779. }
  780. return resultObject;
  781. }
  782.  
  783. private void putAncestor(CacheKey rowKey, Object resultObject, String resultMapId, String columnPrefix) {
  784. if (!ancestorColumnPrefix.containsKey(resultMapId)) {
  785. ancestorColumnPrefix.put(resultMapId, columnPrefix);
  786. }
  787. ancestorObjects.put(rowKey, resultObject);
  788. }
  789.  
  790. //
  791. // NESTED RESULT MAP (JOIN MAPPING)
  792. //
  793.  
  794. private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) {
  795. boolean foundValues = false;
  796. for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {
  797. final String nestedResultMapId = resultMapping.getNestedResultMapId();
  798. if (nestedResultMapId != null && resultMapping.getResultSet() == null) {
  799. try {
  800. final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping);
  801. final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix);
  802. CacheKey rowKey = null;
  803. Object ancestorObject = null;
  804. if (ancestorColumnPrefix.containsKey(nestedResultMapId)) {
  805. rowKey = createRowKey(nestedResultMap, rsw, ancestorColumnPrefix.get(nestedResultMapId));
  806. ancestorObject = ancestorObjects.get(rowKey);
  807. }
  808. if (ancestorObject != null) {
  809. if (newObject) {
  810. linkObjects(metaObject, resultMapping, ancestorObject); // issue #385
  811. }
  812. } else {
  813. rowKey = createRowKey(nestedResultMap, rsw, columnPrefix);
  814. final CacheKey combinedKey = combineKeys(rowKey, parentRowKey);
  815. Object rowValue = nestedResultObjects.get(combinedKey);
  816. boolean knownValue = (rowValue != null);
  817. instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // mandatory
  818. if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw.getResultSet())) {
  819. rowValue = getRowValue(rsw, nestedResultMap, combinedKey, rowKey, columnPrefix, rowValue);
  820. if (rowValue != null && !knownValue) {
  821. linkObjects(metaObject, resultMapping, rowValue);
  822. foundValues = true;
  823. }
  824. }
  825. }
  826. } catch (SQLException e) {
  827. throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'. Cause: " + e, e);
  828. }
  829. }
  830. }
  831. return foundValues;
  832. }
  833.  
  834. private String getColumnPrefix(String parentPrefix, ResultMapping resultMapping) {
  835. final StringBuilder columnPrefixBuilder = new StringBuilder();
  836. if (parentPrefix != null) {
  837. columnPrefixBuilder.append(parentPrefix);
  838. }
  839. if (resultMapping.getColumnPrefix() != null) {
  840. columnPrefixBuilder.append(resultMapping.getColumnPrefix());
  841. }
  842. return columnPrefixBuilder.length() == 0 ? null : columnPrefixBuilder.toString().toUpperCase(Locale.ENGLISH);
  843. }
  844.  
  845. private boolean anyNotNullColumnHasValue(ResultMapping resultMapping, String columnPrefix, ResultSet rs) throws SQLException {
  846. Set<String> notNullColumns = resultMapping.getNotNullColumns();
  847. boolean anyNotNullColumnHasValue = true;
  848. if (notNullColumns != null && !notNullColumns.isEmpty()) {
  849. anyNotNullColumnHasValue = false;
  850. for (String column: notNullColumns) {
  851. rs.getObject(prependPrefix(column, columnPrefix));
  852. if (!rs.wasNull()) {
  853. anyNotNullColumnHasValue = true;
  854. break;
  855. }
  856. }
  857. }
  858. return anyNotNullColumnHasValue;
  859. }
  860.  
  861. private ResultMap getNestedResultMap(ResultSet rs, String nestedResultMapId, String columnPrefix) throws SQLException {
  862. ResultMap nestedResultMap = configuration.getResultMap(nestedResultMapId);
  863. return resolveDiscriminatedResultMap(rs, nestedResultMap, columnPrefix);
  864. }
  865.  
  866. //
  867. // UNIQUE RESULT KEY
  868. //
  869.  
  870. private CacheKey createRowKey(ResultMap resultMap, ResultSetWrapper rsw, String columnPrefix) throws SQLException {
  871. final CacheKey cacheKey = new CacheKey();
  872. cacheKey.update(resultMap.getId());
  873. List<ResultMapping> resultMappings = getResultMappingsForRowKey(resultMap);
  874. if (resultMappings.size() == 0) {
  875. if (Map.class.isAssignableFrom(resultMap.getType())) {
  876. createRowKeyForMap(rsw, cacheKey);
  877. } else {
  878. createRowKeyForUnmappedProperties(resultMap, rsw, cacheKey, columnPrefix);
  879. }
  880. } else {
  881. createRowKeyForMappedProperties(resultMap, rsw, cacheKey, resultMappings, columnPrefix);
  882. }
  883. return cacheKey;
  884. }
  885.  
  886. private CacheKey combineKeys(CacheKey rowKey, CacheKey parentRowKey) {
  887. if (rowKey.getUpdateCount() > 1 && parentRowKey.getUpdateCount() > 1) {
  888. CacheKey combinedKey;
  889. try {
  890. combinedKey = rowKey.clone();
  891. } catch (CloneNotSupportedException e) {
  892. throw new ExecutorException("Error cloning cache key. Cause: " + e, e);
  893. }
  894. combinedKey.update(parentRowKey);
  895. return combinedKey;
  896. }
  897. return CacheKey.NULL_CACHE_KEY;
  898. }
  899.  
  900. private List<ResultMapping> getResultMappingsForRowKey(ResultMap resultMap) {
  901. List<ResultMapping> resultMappings = resultMap.getIdResultMappings();
  902. if (resultMappings.size() == 0) {
  903. resultMappings = resultMap.getPropertyResultMappings();
  904. }
  905. return resultMappings;
  906. }
  907.  
  908. private void createRowKeyForMappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, List<ResultMapping> resultMappings, String columnPrefix) throws SQLException {
  909. for (ResultMapping resultMapping : resultMappings) {
  910. if (resultMapping.getNestedResultMapId() != null && resultMapping.getResultSet() == null) {
  911. // Issue #392
  912. final ResultMap nestedResultMap = configuration.getResultMap(resultMapping.getNestedResultMapId());
  913. createRowKeyForMappedProperties(nestedResultMap, rsw, cacheKey, nestedResultMap.getConstructorResultMappings(),
  914. prependPrefix(resultMapping.getColumnPrefix(), columnPrefix));
  915. } else if (resultMapping.getNestedQueryId() == null) {
  916. final String column = prependPrefix(resultMapping.getColumn(), columnPrefix);
  917. final TypeHandler<?> th = resultMapping.getTypeHandler();
  918. List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);
  919. // Issue #114
  920. if (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) {
  921. final Object value = th.getResult(rsw.getResultSet(), column);
  922. if (value != null) {
  923. cacheKey.update(column);
  924. cacheKey.update(value);
  925. }
  926. }
  927. }
  928. }
  929. }
  930.  
  931. private void createRowKeyForUnmappedProperties(ResultMap resultMap, ResultSetWrapper rsw, CacheKey cacheKey, String columnPrefix) throws SQLException {
  932. final MetaClass metaType = MetaClass.forClass(resultMap.getType(), reflectorFactory);
  933. List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
  934. for (String column : unmappedColumnNames) {
  935. String property = column;
  936. if (columnPrefix != null && !columnPrefix.isEmpty()) {
  937. // When columnPrefix is specified, ignore columns without the prefix.
  938. if (column.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {
  939. property = column.substring(columnPrefix.length());
  940. } else {
  941. continue;
  942. }
  943. }
  944. if (metaType.findProperty(property, configuration.isMapUnderscoreToCamelCase()) != null) {
  945. String value = rsw.getResultSet().getString(column);
  946. if (value != null) {
  947. cacheKey.update(column);
  948. cacheKey.update(value);
  949. }
  950. }
  951. }
  952. }
  953.  
  954. private void createRowKeyForMap(ResultSetWrapper rsw, CacheKey cacheKey) throws SQLException {
  955. List<String> columnNames = rsw.getColumnNames();
  956. for (String columnName : columnNames) {
  957. final String value = rsw.getResultSet().getString(columnName);
  958. if (value != null) {
  959. cacheKey.update(columnName);
  960. cacheKey.update(value);
  961. }
  962. }
  963. }
  964.  
  965. private void linkObjects(MetaObject metaObject, ResultMapping resultMapping, Object rowValue) {
  966. final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject);
  967. if (collectionProperty != null) {
  968. final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);
  969. targetMetaObject.add(rowValue);
  970. } else {
  971. metaObject.setValue(resultMapping.getProperty(), rowValue);
  972. }
  973. }
  974.  
  975. private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMapping, MetaObject metaObject) {
  976. final String propertyName = resultMapping.getProperty();
  977. Object propertyValue = metaObject.getValue(propertyName);
  978. if (propertyValue == null) {
  979. Class<?> type = resultMapping.getJavaType();
  980. if (type == null) {
  981. type = metaObject.getSetterType(propertyName);
  982. }
  983. try {
  984. if (objectFactory.isCollection(type)) {
  985. propertyValue = objectFactory.create(type);
  986. metaObject.setValue(propertyName, propertyValue);
  987. return propertyValue;
  988. }
  989. } catch (Exception e) {
  990. throw new ExecutorException("Error instantiating collection property for result '" + resultMapping.getProperty() + "'. Cause: " + e, e);
  991. }
  992. } else if (objectFactory.isCollection(propertyValue.getClass())) {
  993. return propertyValue;
  994. }
  995. return null;
  996. }
  997.  
  998. }

Mybatis源码分析之结果封装ResultSetHandler和DefaultResultSetHandler的更多相关文章

  1. mybatis 源码分析(八)ResultSetHandler 详解

    本篇博客就是 myabtis 系列的最后一篇了,还剩 ResultSetHandler 没有分析:作为整个 mybatis 最复杂最繁琐的部分,我不打算按步骤一次详解,因为里面的主要内容就是围绕 re ...

  2. 精尽MyBatis源码分析 - SQL执行过程(三)之 ResultSetHandler

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  3. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  4. 【MyBatis源码分析】select源码分析及小结

    示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...

  5. Mybatis源码分析-StatementHandler

    承接前文Mybatis源码分析-BaseExecutor,本文则对通过StatementHandler接口完成数据库的CRUD操作作简单的分析 StatementHandler#接口列表 //获取St ...

  6. MyBatis 源码分析 - 插件机制

    1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展.这样的好处是显而易见的,一是增加了框架的灵活性.二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作.以 My ...

  7. MyBatis 源码分析 - 配置文件解析过程

    * 本文速览 由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括.本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settings,typeAl ...

  8. Mybatis源码分析

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  9. Mybatis源码分析之SqlSession和Excutor(二)

    通过上一篇文章的分析我们,我初步了解了它是如何创建sessionFactory的(地址:Mybatis源码分析之SqlSessionFactory(一)), 今天我们分析下Mybatis如何创建Sql ...

随机推荐

  1. Debugging TensorFlow models 调试 TensorFlow 模型

    Debugging TensorFlow models Symbolic nature of TensorFlow makes it relatively more difficult to debu ...

  2. java集合之HashMap源码解读

    源自:jdk1.8.0_121 HashMap继承自AbstractMap,实现了Map.Cloneable.Serializable. HashMap内部是由数组.链表.红黑树实现的 变量 // 默 ...

  3. SpringMVC中url-pattern /和/*的区别

    http://blog.csdn.net/u010648555/article/details/51612030

  4. SCNN车道线检测--(SCNN)Spatial As Deep: Spatial CNN for Traffic Scene Understanding(论文解读)

    Spatial As Deep: Spatial CNN for Traffic Scene Understanding 收录:AAAI2018 (AAAI Conference on Artific ...

  5. dataview findrows

    DataView dvStu = dsStu.Tables[0].Copy().DefaultView;//当前学年学期下所有学生 dvStu.Sort = "bjmc,xm"; ...

  6. WebApplicationContext类的作用

    WebApplicationContext是实现ApplicationContext接口的子类.是专门为WEB应用准备的.作用: 1.它允许从相对于Web根目录的路径中加载配置文件完成初始化工作.从W ...

  7. Uncaught (in promise) TypeError:的错误

    1.错误 创建一个vue实例,在data定义一些变量,如activityTime. 在methods里面用了axios发送请求. 在then的回调里使用this.activityTime 报错! 2. ...

  8. Django项目实战之用户头像上传与访问

      1 将文件保存到服务器本地 upload.html <!DOCTYPE html> <html lang="en"> <head> < ...

  9. ionic安装教程

    首先是安装node.js,通过nodejs官网下载,网址https://nodejs.org/en/.如果下载许要教程推荐这个https://www.cnblogs.com/zhouyu2017/p/ ...

  10. Docker 数据卷

    数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性: 数据卷可以在容器之间共享和重用 对数据卷的修改会立马生效 对数据卷的更新,不会影响镜像 卷会一直存在,直到没有容 ...