DeferredLoad

作者: 93张先生 | 来源:发表于2020-09-13 17:16 被阅读0次

DeferredLoad

DeferredLoad 是定义在 BaseExecutor 中的内部类,它负责从 localCache 缓存中延迟加载结果对象。

BaseExecutor 中缓存的第一种功能,也就是缓存结查询得到的结果对象。除此之外,一级缓存还有第二个功能:前面在分析嵌套查询时,如果一级缓存中缓存了嵌套查询的结果对象,则可以从一级缓存中直接加载该结果对象:如果一级缓存中记录的嵌套查询的结对象并未完全加载,则可以通过 DeferredLoad 实现类似延迟加载的功能。

Executor 中与上述功能直接相关的方法有两个,一个是 isCached()方法负责检测是否缓存指定查询的结果对象,另一个是 deferLoad() 方法 ,它负责创建 DeferredLoad 象并将其添加到 deferredLoads 集合中。

  /**
   * 检测是否缓存了 key
   * @param ms
   * @param key
   * @return
   */
  @Override
  public boolean isCached(MappedStatement ms, CacheKey key) {
    return localCache.getObject(key) != null;
  }

  /**
   * 创建 DeferredLoad 对象,并添加到 deferredLoads 队列中
   * @param ms
   * @param resultObject
   * @param property
   * @param key
   * @param targetType
   */
  @Override
  public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    DeferredLoad deferredLoad = new DeferredLoad(resultObject, property, key, localCache, configuration, targetType);
    if (deferredLoad.canLoad()) {
      // 一级缓存中已经记录了指定查询的结果对象,直接从缓存中加载对象,并设置到外层对象中
      deferredLoad.load();
    } else {
      // 将 DeferredLoad 对象添加到 deferredLoads 队列中,待整个外层查询结束后,再加载该结果对象
      deferredLoads.add(new DeferredLoad(resultObject, property, key, localCache, configuration, targetType));
    }
  }
DeferredLoad 类
  /**
   * 从 localCache 缓存中,延迟加载结果对象;
   * 前面在分析嵌套查询时,如果一级缓存中缓存了嵌套查询的结果对象,则可以从一级缓存中直接加载该结果对象:如果一级缓存中记录的嵌套查询的结对象并未完全加载,则可以通过 DeferredLoad 实现类似延迟加载的功能。
   * 针对一对多的嵌套查询,它只实现了懒查询,它并没有真正的去查询数据库
   * https://blog.csdn.net/liuao107329/article/details/41829767
   */
  private static class DeferredLoad {
    // 外层对象对应的 MetaObject 对象
    private final MetaObject resultObject;
    // 延迟加载的属性名称
    private final String property;
    // 延迟加载的属性类型
    private final Class<?> targetType;
    // 延迟加载的结果对象在一级缓存中相应的 CacheKey 对象
    private final CacheKey key;
    // 一级缓存,与 BaseExecutor.localCache 字段指向同一 PerpetualCache 对象
    private final PerpetualCache localCache;
    private final ObjectFactory objectFactory;
    // 负责结果对象的类型转换
    private final ResultExtractor resultExtractor;

    // issue #781
    public DeferredLoad(MetaObject resultObject,
                        String property,
                        CacheKey key,
                        PerpetualCache localCache,
                        Configuration configuration,
                        Class<?> targetType) {
      this.resultObject = resultObject;
      this.property = property;
      this.key = key;
      this.localCache = localCache;
      this.objectFactory = configuration.getObjectFactory();
      this.resultExtractor = new ResultExtractor(configuration, objectFactory);
      this.targetType = targetType;
    }

    /**
     * 检测缓存项 是否缓存,还有查询数据库是否已经查询完毕
     * @return
     */
    public boolean canLoad() {
      // 是否缓存,还有缓存已经查询完毕
      return localCache.getObject(key) != null && localCache.getObject(key) != EXECUTION_PLACEHOLDER;
    }

    /**
     * 从缓存加载对象,并结果对象类型转换
     */
    public void load() {
      @SuppressWarnings("unchecked")
      // we suppose we get back a List
      // 查询缓存对象
      List<Object> list = (List<Object>) localCache.getObject(key);
      // 将缓存的结果对象转换成指定类型
      Object value = resultExtractor.extractObjectFromList(list, targetType);
      // 设置到外层对象的对应属性
      resultObject.setValue(property, value);
    }

  }

相关文章

  • DeferredLoad

    DeferredLoad DeferredLoad 是定义在 BaseExecutor 中的内部类,它负责从 lo...

网友评论

    本文标题:DeferredLoad

    本文链接:https://www.haomeiwen.com/subject/fmakektx.html