ibatis缓存的设置使用

(一)背景

简而言之一句话,减少服务器处理次数,加快访问速度。

(二)ibatis缓存的使用方法

在要使用的xml模块中添加cacheModel模块,例如:


<cacheModel id="user-cache" type="LRU" readOnly="false"

serialize="true">

<flushInterval hours="24" />

<flushOnExecute statement="getUser" />

<property value="600" name="size" />

</cacheModel>


(三)属性参数说明


id : 缓存模块cacheModel唯一性的标志。

    type: 缓存的类型。目前使用的缓存类型有四种:

FIFO:com.ibatis.sqlmap.engine.cache.fifo.FifoCacheController

LRU:com.ibatis.sqlmap.engine.cache.fifo.LruCacheController

MEMORY:com.ibatis.sqlmap.engine.cache.fifo.MemoryCacheController

OSCACHE:com.ibatis.sqlmap.engine.cache.fifo.OSCacheController

当然,你也可以自己来实现Cache, 你需要做的是让你的Cache类 implements com.ibatis.sqlmap.engine.cache.CacheController. 

readOnly:是否只读. 默认为true, 只读。

Serialize:是否从Cache中读取同一个对象,还是对象的副本。只有在readOnly=false才有效. 
   因为Cache是只读的,那么为不同session返回的对象肯定是一个. 
   只有在Cache是可读写的时候,才需要为每个session返回对象的副本. 

这种缓存为每一个Session返回缓存对象不同的实例(复本)。因此每一个Session都可以安全修改返回的对象. 注意,此时readOnly必须为false。如果你把它设为 true ,记得检查两件事,一件事是缓存中存放的对象(你想查询的POJO)必须是可序列化的,即实现Serializable接口。如果你有一个复杂对象属性,它也必须满足这个规则,你的整个对象树必须是可序列化的。另一件事是关闭sql-map-config中的延迟加载属性,即lazyload=false,原因是,它使用了动态代理机制,那个代理对象并不是Serializable的。

flushInterval:Cache刷新间隔. 可以配置hours,minutes,seconds,milliseconds. 

注:不是说间隔时间到了,在cache的statement会自己刷新,而是说,见间隔时间过了后,在下次的查询的时候,江不会是直接去cache中拿值,而会用sql去取值,也就是: 如果,间隔时间过了,还没有Cache对应的statement执行的话,那么Cache中就会一直是旧的,不用担心Cache数据是旧的,因为下次的查询将会直接从SQL查询,而非Cache,查询的结果也会去更新Cache的值。

一个 cacheModel 只能有一个 flushInteval 元素

flushOnExecute :当这些statement被执行了,那么下次的查询将会通过SQL去查,同时用查询结果更新Cache. 
注: 和flushInterval的刷新一样,不是主动刷新,而是由下次查询来触发被动刷新。
在一个cacheModel中可以指定多个flushOnExecute。

statement:就是需要被执行的statement的id

cacheModel可以定义任意多的flushOnExecute元素

property:这是针对cacheModel的额外的一些属性配置.不同type的cacheModel将会有自己专有的一些property配置. 

在 LRU cache model 中,cache-size指定了缓存储存的项数

FIFO: <property name="size" value="100" /> 
LRU: <property name="cache-size" value="100" /> 
MEMORY: <property name="reference-type" value="WEAK" />

(四)使用示例

在statment的使用上,直接加一个cacheModel属性指向id即可。

<select id="getAllUser" resultClass="user" cacheModel="user-cache">

select * from user;

</select>

(五)注意事项

1)MEMORY 没有统一的对象重用模式的应用,或内存不足的应用。

WEAK是默认,大多数情况下是最好的选择,能大大提高查用查询的性能,但对于当前不被使用的查询结果数据,将被清除以释放内存来分配其他对象。
LRU  实现用近期最少使用的原则来确定如何从Cache中清除对象。对于较长的时间内,一些用户经常使用某些特定对象的情况(例如,在PaginatedList和常用的查询关键字结果集中翻页),LRU Cache是不错的选择。

size必须为整数,代表保存在Cache的中对象的最大数目。因此不要Cache太多的对象,以免内存不足。
FIFO  实现用先进先出的原则来确定如何从Cache中清除对象。对于短时间内持续引用特定的查询而后很可能不再使用的情况,FIFO是很好的选择。
根据个人实践,内存充足时使用LRU,否则使用MEMORY(WEAK)通常能获得较好的效果。

2)

如果多个select使用了同一个Cache Model,这样几个select的cache结果都会被一起清除掉。cacheModel 的property元素用来为各个不同类型的缓存定义其特定的属性及其属性的value。
Ibatis的缓存方案跟传统O/R Mapping的缓存方案还是有所区别的。传统的OR Mapping会根据Ojbect的唯一标识符来缓存,这样当多次不同的结果返回相同结果的时候,对象只会被cache一次,而ibatis是直接对完全的结果进行缓存,而不管是否已经有相同的对象在cache中存在了。
3)
readonly和serialize的组合会影响到应用程序的性能,

readonly serialize 结果 
true false 好 
false true 好 
false false 警告 
true true 差 

4)缓存类型

MEMORY类型的cache只是简单的将cache的数据放入到内存中,只到GC将其释放。Memory类型的cache只有一个属性reference-type,其值可以是WEAK、SOFT、Strong三种类型的引用。使用WEAK、SOFT这两种引用,GC会根据内存的使用情况和缓存内容的访问状况来决定缓存内容的清除还是保留。而使用Strong引用缓存起来的内容会一直保留下来只到被Flush掉。下面是该类型缓存使用样例。
view plaincopy to clipboardprint?
<cacheModel id="categoryCache" type="MEMORY">  
   <flushInterval hours="24"/>  
   <flushOnExecute statement="insert"/>  
   <flushOnExecute statement="update"/>  
   <flushOnExecute statement="delete"/>  
   <property name="reference-type" value="WEAK"/>  
</cacheModel>   
<cacheModel id="categoryCache" type="MEMORY">
   <flushInterval hours="24"/>
   <flushOnExecute statement="insert"/>
   <flushOnExecute statement="update"/>
   <flushOnExecute statement="delete"/>
   <property name="reference-type" value="WEAK"/>
</cacheModel> 

   LRU类型的cache有一个最大缓存数,当保存的数量超过这个值的时候,Ibatis会依据“least recently used”的算法将数据从缓存中清除。LRU类型的缓存惟一可以设置的属性就是这个最大缓存数。下面是该类型缓存使用样例。
view plaincopy to clipboardprint?
<cacheModel id="categoryCache" type="LRU">  
   <flushInterval hours="24"/>  
   <flushOnExecute statement="insert"/>  
   <flushOnExecute statement="update"/>  
   <flushOnExecute statement="delete"/>  
   <property name="size" value="200"/>  
</cacheModel>  
<cacheModel id="categoryCache" type="LRU">
   <flushInterval hours="24"/>
   <flushOnExecute statement="insert"/>
   <flushOnExecute statement="update"/>
   <flushOnExecute statement="delete"/>
   <property name="size" value="200"/>
</cacheModel> 

   FIFO类型cache跟LRU类型的缓存类似也有一个固定的SIZE,不同的是其使用使用的是“先进先出”的策略。该类型的缓存惟一可以设置的属性就是这个最大缓存数。下面是该类型缓存使用样例。
view plaincopy to clipboardprint?
<cacheModel id="categoryCache" type="FIFO">  
   <flushInterval hours="24"/>  
   <flushOnExecute statement="insert"/>  
   <flushOnExecute statement="update"/>  
   <flushOnExecute statement="delete"/>  
   <property name="size" value="1000"/>  
</cacheModel>  
<cacheModel id="categoryCache" type="FIFO">
   <flushInterval hours="24"/>
   <flushOnExecute statement="insert"/>
   <flushOnExecute statement="update"/>
   <flushOnExecute statement="delete"/>
   <property name="size" value="1000"/>
</cacheModel> 

 OSCACHE类型的cache值得就是使用OpenSymphony的oscache作为cache的实现方案。


OSCACHE 实现不使用 property 元素,而是在类路径的根路径中使用标准的oscache.properties 文件进行配置。在 oscache.properties文件中,您可以配置 Cache 的算法(和上面讨论的算法很类似),Cache 的大小,持久化方法(内存,文件等)和集群方法

(六)遇到的问题

1)使用flushOnExecute 标签的时候,启动项目的时候一直报错,报的是sqlmap的配置问题

调查了很久,最后发现问题:我最初是这样写的 :

<span style="color:#323e32;">	<cacheModel id="messageTemplate-cache" type="FIFO" readOnly="true"  
        serialize="true">  
        <flushInterval hours="24" />  
       </span><span style="color:#ff0000;"> <flushOnExecute statement="refreshCache"/>
        <flushOnExecute statement="insert"/></span><span style="color:#323e32;">
        <property name="size" value="3000" />  
    </cacheModel>
    
    <select id="refreshCache">
    	select 1
    </select></span>
可以看到红色标注的地方,我在使用的statement中没有添加namespace,主要是因为之前写sqlmap的时候都不写的,以为是默认添加,但是这边起始不是这样的。

正确的写法:

<span style="color:#323e32;">	<cacheModel id="messageTemplate-cache" type="FIFO" readOnly="true"  
        serialize="true">  
        <flushInterval hours="24" />  
     </span><span style="color:#ff0000;">   <flushOnExecute statement="MessageTemplate.refreshCache"/>
        <flushOnExecute statement="MessageTemplate.insert"/></span><span style="color:#323e32;">
        <property name="size" value="3000" />  
    </cacheModel>
    
    <select id="refreshCache">
    	select 1
    </select></span>


需要注意的是如果statement对应的sqlmap使用了namespace,statement就要填写完整的语句名称,即便statement引用的映射语句就在同个namespace中,如果statement引用的映射语句在其他的sqlmap配置文件中,那就要保证引用的语句

(七)总结

1、 感觉ibatis的缓存到了一定的时候就会有瓶颈,在实际应用中如果把数据层的cache做到应用层效果应该会更好。

2、 Ibatis设置cache,当session设为 true 的时候,缓存中存放的对象(你想查询的POJO)必须是可序列化的,即实现Serializable接口,而且只能是jdk自带的序列化。如果你有一个复杂对象属性,它也必须满足这个规则,你的整个对象树必须是可序列化的



readonly和serialize的组合会影响到应用程序的性能,

readonly serialize 结果 
true false 好 
false true 好 
false false 警告 
true true 差 
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值