CachingStatement在执行查询的时候,会先从CacheModel中获取结果。如果结果为空,则执行查询并将结果保存在CacheModel中。在读写CacheModel的过程中,都需要获得CacheKey对象,以CacheKey作为缓存的key。下面是获得CacheKey的过程:
CachingStatement
public CacheKey getCacheKey(StatementScope statementScope, Object parameterObject) {
//调用了MappedStatement的getCacheKey
CacheKey key = statement.getCacheKey(statementScope, parameterObject);
//如果cacheModel不是只读的而且不是可序列化的,则将当前的session信息作为CacheKey的一部分
if (!cacheModel.isReadOnly() && !cacheModel.isSerialize()) {
key.update(statementScope.getSession());
}
return key;
}
MappedStatement中获得CacheKey的时候使用了几个因素:sql语句的id,baseCacheKey和sql语句本身
sdf
MappedStatement
public CacheKey getCacheKey(StatementScope statementScope, Object parameterObject) {
Sql sql = statementScope.getSql();
ParameterMap pmap = sql.getParameterMap(statementScope, parameterObject);
//调用ParameterMap的方法
CacheKey cacheKey = pmap.getCacheKey(statementScope, parameterObject);
cacheKey.update(id);
cacheKey.update(baseCacheKey);
cacheKey.update(sql.getSql(statementScope, parameterObject)); //Fixes bug 953001
return cacheKey;
}
ParameterMap
public CacheKey getCacheKey(StatementScope statementScope, Object parameterObject) {
return dataExchange.getCacheKey(statementScope, this, parameterObject);
}
BaseDataExchange中 调用了PrimitiveDataExchange的getData,用getData得到的数组来更新key,也就是使用这次sql调用的参数值来更新key。
BaseDataExchange
public CacheKey getCacheKey(StatementScope statementScope, ParameterMap parameterMap, Object parameterObject) {
CacheKey key = new CacheKey();
Object[] data = getData(statementScope, parameterMap, parameterObject);
for (int i = 0; i < data.length; i++) {
if (data[i] != null) {
key.update(data[i]);
}
}
return key;
}
PrimitiveDataExchange从ParameterMap中获得参数的个数,创建对象数组data,将parameterObject付给数组的每个元素。
PrimitiveDataExchange
public Object[] getData(StatementScope statementScope, ParameterMap parameterMap, Object parameterObject) {
ParameterMapping[] mappings = parameterMap.getParameterMappings();
Object[] data = new Object[mappings.length];
for (int i = 0; i < mappings.length; i++) {
data[i] = parameterObject;
}
return data;
}
CacheKey的update方法,增加参数计数值,修改checksum和baseHashCode,使用参数的hashcode值和caseHashCode来更新当前cachekey的hashcode
CacheKey
public CacheKey update(Object object) {
int baseHashCode = object.hashCode();
count++;
checksum += baseHashCode;
baseHashCode *= count;
hashcode = multiplier * hashcode + baseHashCode;
paramList.add(object);
return this;
}
综上所述,计算cachekey的因素包括baseHashCode,sql语句的id,sql语句本身和每次调用传入的sql参数值。如果cacheModel不是只读的而且不是可序列化的,则将当前的session信息也作为CacheKey的一部分。