MyBatis源码分析(4)—— Cache构建以及应用
@(MyBatis)[Cache]
MyBatis源码分析——Cache构建以及应用
SqlSession使用缓存流程
如果开启了二级缓存,而Executor会使用CachingExecutor来装饰,添加缓存功能,该CachingExecutor会从MappedStatement中获取对应的Cache来使用。(注:MappedStatement中有保存相关联的Cache)
在使用SqlSession向DB查询数据时,如果开启了二级缓存,则会优先从二级缓存中获取数据,没有命中的话才会去查询一级缓存,此时,一级缓存也没有命中,则才会真正的去数据库查询数据。
没有命中缓存
下图为开启了二级缓存的查询数据时序图,其中忽略了二级缓存事务的处理(见下面二级缓存详细说明)。

命中二级缓存

命中一级缓存

缓存键,CacheKey
下面为CacheKey的主要核心代码,省略了部分代码。在MyBatis中,是通过几个条件来判断是否同一条Sql的。
判断条件:
- Statement ID
- 结果范围
- Sql
- 所有的入参
在上面的条件中,对于需要使用JDBC查询出相同结果的来说,需要是同一条Sql以及该Sql的入参条件。
在查询数据之前,会先创建CacheKey,在BaseExecutor.createCacheKey中实现:
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
if (closed) throw new ExecutorException("Executor was closed.");
CacheKey cacheKey = new CacheKey();
// StatementId, 即用于映射Mapper中的具体Sql的ID
cacheKey.update(ms.getId());
// 结果集范围,在数据库查询出来的结果中进行过滤,并非是物理分页。
cacheKey.update(rowBounds.getOffset());
cacheKey.update(rowBounds.getLimit());
// 具体执行的Sql
cacheKey.update(boundSql.getSql());
// 入参变量值
List
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
for (int i = 0; i < parameterMappings.size(); i++) { // mimic DefaultParameterHandler logic
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
cacheKey.update(value);
}
}
return cacheKey;
}
CacheKey的实现:
这里将所有需要判断相等的条件都放入List中,并且更新这些条件计算出校验值和hashCode,这是为了加快比较的速度。因为只有在校验值以及HashCode相等的情况下,才会去逐一地判断每个条件是否相等。
public class CacheKey implements Cloneable, Serializable {
// 默认扩展因子
private static final int DEFAULT_MULTIPLYER = 37;
// 默认HashCdoe基值
private static final int DEFAULT_HASHCODE = 17;
private int multiplier;
private int hashcode;
private long checksum;
private int count;
private List

浙公网安备 33010602011771号