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的一部分。