ibatis缓存的简单使用和源码分析
配置:
??? <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" resultparametercacheModel="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;
? }
?