首页 > 技术文章 > mybatis-查询延迟加载功能

ironroot 2018-03-07 16:06 原文

 

SqlSession.getMapper -> 

   configuration.getMapper ->

      mapperRegistry.getMapper ->

        mapperProxyFactory.newInstance  返回mapper的代理对象 mapperProxy, 接口的查询、更新等方法通过动态代理技术由mapperProxy来代理执行。

 

 

mapperProxy.invoke ->

     mapperMethod.execute ->   根据不同的sql类型执行 INSERT,UPDATE,DELETE,SELECT,FLUSH

      SELECT  : sqlSession.selectList  - >

              configuration.getMappedStatement -> 

                        cachingExecutor.query ->   实际上委托 baseExecutor来执行的查询默认开启一级缓存,当开启 二级缓存的时候可以缓存查询结果

                                baseExecutor.queryFromDatabase- >  

                                         RoutingStatementHandler.query -> 通过 configuration.newStatementHandler获得

                                                     DefaultResultSetHandler.handleResultSets ->   获取 mapperStatement即xml里定义的resultMap标签,根据resultMap组装查询返回结果,如果接口方法中没有ResultHandler参数,则使用DefaultResultHandler来处理结果

                                                        

 

 1 private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {
 2     final ResultLoaderMap lazyLoader = new ResultLoaderMap();
 3     //创建结果对象,如果有延迟加载的属性,则创建代理对象
 4     Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);
 5     if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
 6       final MetaObject metaObject = configuration.newMetaObject(rowValue);
 7       boolean foundValues = this.useConstructorMappings;
 8      //自动映射结果对象属性,当XML里没有定义的时候也能自动映射
 9       if (shouldApplyAutomaticMappings(resultMap, false)) {
10         foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;
11       }
12      //有属性需要延迟加载的时候,调用lazyLoader.addLoader添加 延迟加载器
13       foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;
14       foundValues = lazyLoader.size() > 0 || foundValues;
15       rowValue = (foundValues || configuration.isReturnInstanceForEmptyRow()) ? rowValue : null;
16     }
17     return rowValue;
18   }

 

  

 1 //查询嵌套的resultMap属性值  
 2 private Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)
 3       throws SQLException {
 4     final String nestedQueryId = propertyMapping.getNestedQueryId();
 5     final String property = propertyMapping.getProperty();
 6     final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);
 7     final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();
 8     final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, propertyMapping, nestedQueryParameterType, columnPrefix);
 9     Object value = null;
10     if (nestedQueryParameterObject != null) {
11       final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);
12       final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);
13       final Class<?> targetType = propertyMapping.getJavaType();
14       if (executor.isCached(nestedQuery, key)) {
15         executor.deferLoad(nestedQuery, metaResultObject, property, key, targetType);
16         value = DEFERED;
17       } else {
18         final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);
19          //添加属性延迟加载器!!!!
20         if (propertyMapping.isLazy()) {
21           lazyLoader.addLoader(property, metaResultObject, resultLoader);
22           value = DEFERED;
23         } else {
24           value = resultLoader.loadResult();
25         }
26       }
27     }
28     return value;
29   }

 

当返回结果对象查询延迟属性的时候触发动态代理

 

 1 @Override
 2     public Object invoke(Object enhanced, Method method, Method methodProxy, Object[] args) throws Throwable {
 3       final String methodName = method.getName();
 4       try {
 5         synchronized (lazyLoader) {
 6           if (WRITE_REPLACE_METHOD.equals(methodName)) {
 7             Object original;
 8             if (constructorArgTypes.isEmpty()) {
 9               original = objectFactory.create(type);
10             } else {
11               original = objectFactory.create(type, constructorArgTypes, constructorArgs);
12             }
13             PropertyCopier.copyBeanProperties(type, enhanced, original);
14             if (lazyLoader.size() > 0) {
15               return new JavassistSerialStateHolder(original, lazyLoader.getProperties(), objectFactory, constructorArgTypes, constructorArgs);
16             } else {
17               return original;
18             }
19           } else {
20             //当查询的属性为延迟加载的属性时,LazyHolder
21 进行延迟加载
22             if (lazyLoader.size() > 0 && !FINALIZE_METHOD.equals(methodName)) {
23               if (aggressive || lazyLoadTriggerMethods.contains(methodName)) {
24                 lazyLoader.loadAll();
25               } else if (PropertyNamer.isSetter(methodName)) {
26                 final String property = PropertyNamer.methodToProperty(methodName);
27                 lazyLoader.remove(property);
28               } else if (PropertyNamer.isGetter(methodName)) {
29                 final String property = PropertyNamer.methodToProperty(methodName);
30                 if (lazyLoader.hasLoader(property)) {
31                   //延迟加载
32                   lazyLoader.load(property);
33                 }
34               }
35             }
36           }
37         }
38         return methodProxy.invoke(enhanced, args);
39       } catch (Throwable t) {
40         throw ExceptionUtil.unwrapThrowable(t);
41       }
42     }
43   }

 

 

 

至此,延迟加载逻辑结束!!

                                                         

                                                         

推荐阅读