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);
}
}
网友评论