IBatis 的缓存机制之 Select Query缓存

14 篇文章 0 订阅
7 篇文章 0 订阅

 

原文地址:http://lifei114.javaeye.com/admin/blogs/581795

 

IBatis 的缓存机制之 Select Query缓存

 

可以按下面的代码在你的 SqlMap.xml 里配置,如下:

 

< cacheModel id ="users-cache" imlementation ="LRU" readOnly ="true" serialize ="true" >
< flushInterval hours ="24" />
< flushOnExecute statement ="users.update" />
< property name ="size" value ="1000" />
</ cacheModel >

< statement id ="findUsers" parameterClass ="int" cacheModel ="users-cache" >
select * from users where member_id = #value#
</ statement >

 

我们来跟踪一下代码,看 IBatis 是如何实现缓存的,

还是由类:SqlMapParser 来解析这个配置的,代码如下:

 

  1. private void addCacheModelNodelets() {  
  2.    parser.addNodelet("/sqlMap/cacheModel"new Nodelet() {  
  3.      public void process(Node node) throws Exception {  
  4.        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());  
  5.        String id = state.applyNamespace(attributes.getProperty("id"));  
  6.        String type = attributes.getProperty("type");  
  7.        String readOnlyAttr = attributes.getProperty("readOnly");  
  8.        Boolean readOnly = readOnlyAttr == null || readOnlyAttr.length() <= 0 ? null : new Boolean("true".equals(readOnlyAttr));  
  9.        String serializeAttr = attributes.getProperty("serialize");  
  10.        Boolean serialize = serializeAttr == null || serializeAttr.length() <= 0 ? null : new Boolean("true".equals(serializeAttr));  
  11.        type = state.getConfig().getTypeHandlerFactory().resolveAlias(type);  
  12.        Class clazz = Resources.classForName(type);  
  13.        if (readOnly == null) {  
  14.          readOnly = Boolean.TRUE;  
  15.        }  
  16.        if (serialize == null) {  
  17.          serialize = Boolean.FALSE;  
  18.        }  
  19.        CacheModelConfig cacheConfig = state.getConfig().newCacheModelConfig(id, (CacheController) Resources.instantiate(clazz), readOnly.booleanValue(), serialize.booleanValue());  
  20.        state.setCacheConfig(cacheConfig);  
  21.      }  
  22.    });  
  23.    parser.addNodelet("/sqlMap/cacheModel/end()"new Nodelet() {  
  24.      public void process(Node node) throws Exception {  
  25.        state.getCacheConfig().setControllerProperties(state.getCacheProps());  
  26.      }  
  27.    });  
  28.    parser.addNodelet("/sqlMap/cacheModel/property"new Nodelet() {  
  29.      public void process(Node node) throws Exception {  
  30.        state.getConfig().getErrorContext().setMoreInfo("Check the cache model properties.");  
  31.        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());  
  32.        String name = attributes.getProperty("name");  
  33.        String value = NodeletUtils.parsePropertyTokens(attributes.getProperty("value"), state.getGlobalProps());  
  34.        state.getCacheProps().setProperty(name, value);  
  35.      }  
  36.    });  
  37.    parser.addNodelet("/sqlMap/cacheModel/flushOnExecute"new Nodelet() {  
  38.      public void process(Node node) throws Exception {  
  39.        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());  
  40.        String statement = childAttributes.getProperty("statement");  
  41.        state.getCacheConfig().addFlushTriggerStatement(statement);  
  42.      }  
  43.    });  
  44.    parser.addNodelet("/sqlMap/cacheModel/flushInterval"new Nodelet() {  
  45.      public void process(Node node) throws Exception {  
  46.        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());  
  47.        try {  
  48.          int milliseconds = childAttributes.getProperty("milliseconds") == null ? 0 : Integer.parseInt(childAttributes.getProperty("milliseconds"));  
  49.          int seconds = childAttributes.getProperty("seconds") == null ? 0 : Integer.parseInt(childAttributes.getProperty("seconds"));  
  50.          int minutes = childAttributes.getProperty("minutes") == null ? 0 : Integer.parseInt(childAttributes.getProperty("minutes"));  
  51.          int hours = childAttributes.getProperty("hours") == null ? 0 : Integer.parseInt(childAttributes.getProperty("hours"));  
  52.          state.getCacheConfig().setFlushInterval(hours, minutes, seconds, milliseconds);  
  53.        } catch (NumberFormatException e) {  
  54.          throw new RuntimeException("Error building cache in '" + "resourceNAME" + "'.  Flush interval milliseconds must be a valid long integer value.  Cause: " + e, e);  
  55.        }  
  56.      }  
  57.    });  
  58.  } 

 带缓存的SQL具体的执行是由类:CachingStatement  来执行,如要执行executeQueryForList动作,其执行的代码如下:

 

  1. public List executeQueryForList(StatementScope statementScope, Transaction trans, Object parameterObject, int skipResults, int maxResults)  
  2.     throws SQLException {  
  3.   CacheKey cacheKey = getCacheKey(statementScope, parameterObject);  
  4.   cacheKey.update("executeQueryForList");  
  5.   cacheKey.update(skipResults);  
  6.   cacheKey.update(maxResults);  
  7.   Object listAsObject = cacheModel.getObject(cacheKey);  
  8.   List list;  
  9.   if(listAsObject == CacheModel.NULL_OBJECT){  
  10.     // The cached object was null  
  11.     list = null;  
  12.   }else if (listAsObject == null) {  
  13.     list = statement.executeQueryForList(statementScope, trans, parameterObject, skipResults, maxResults);  
  14.     cacheModel.putObject(cacheKey, list);  
  15.   }else{  
  16.     list = (List) listAsObject;  
  17.   }  
  18.   return list;  

中去,再次使用时就直接返回缓存里的数据了。

这里面的 CacheKey 很有意思,Ibatis 是按照 SQL 加参数并加参数个数进行 Hash 组成一个 Key。因此我们的查询中 SQL的参数变化的频率太多时,使用缓存的效果将十分不明显,

甚至可能取得相反的效果,每次查询缓存也是需要时间的。

具体项目中如何使用缓存我认为具体问题具体分析,不要盲目相信科学神话,“大家都在用的东西不一定就适合自己用”

  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;
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值