配置:
<cacheModel type="LRU" id="user-cache">
<flushInterval hours="24"/>
<flushOnExecute statement="user.addUser"/>
<flushOnExecute statement="user.updateUser"/>
<flushOnExecute statement="user.deleteUser"/>
<property name="cache-size" value="50000"/>
</cacheModel>
<select id="getAll" resultClass="user" parameterClass="java.util.HashMap" cacheModel="user-cache">
select * from user limit 0,#size#
</select>
测试代码:
Map<String, Object> map = new HashMap<String, Object>();
map.put("size", 8);
// first time no cache
Long startTime = System.currentTimeMillis();
List<User> list = (List<User>)sqlMap.queryForList("user.getAll", map);
System.out.println("No cache pass time:" + (System.currentTimeMillis() - startTime));
// second time has cache
map.put("size", 8);
startTime = System.currentTimeMillis();
list = (List<User>)sqlMap.queryForList("user.getAll", map);
System.out.println("Has cache pass time:" + (System.currentTimeMillis() - startTime));
结果:
No cache pass time:485
Has cache pass time:0
打开ibatis的日志,会发现第二次执行没有sql语句输出。
注意:
CacheModel缓存的是statement,即key是跟sql语句相关,如果sql语句不一样,将产生两个cache,如第二条将使用不到缓存,但第三条可以使用缓存:
select * from user limit 0,4 新建缓存
select * from user limit 0,8 新建缓存
select * from user limit 0,8 使用缓存
简单源码分析:
以queryForList为例:
SqlMapExecutorDelegate具体实现:
list = ms.executeQueryForList(statementScope, trans, paramObject, skip, max);
这里ms为MappedStatement,其中CachingStatement是它的子类。
CachingStatement具体实现:
public List executeQueryForList(StatementScope statementScope, Transaction trans, Object parameterObject, int skipResults, int maxResults)
throws SQLException {
CacheKey cacheKey = getCacheKey(statementScope, parameterObject);
cacheKey.update("executeQueryForList");
cacheKey.update(skipResults);
cacheKey.update(maxResults);
Object listAsObject = cacheModel.getObject(cacheKey);
List list;
if(listAsObject == CacheModel.NULL_OBJECT){
// The cached object was null
list = null;
}else if (listAsObject == null) {
list = statement.executeQueryForList(statementScope, trans, parameterObject, skipResults, maxResults);
cacheModel.putObject(cacheKey, list);
}else{
list = (List) listAsObject;
}
return list;
}