使用IBatis作数据缓存
1.SqlMapConfig.xml中
<settingscacheModelsEnabled="true" //设置为trueenhancementEnabled="true"lazyLoadingEnabled="true"............./>2.cacheModel cacheModel的属性值等于指定的cacheModel元素的name属性值。属性cacheModel定义查询mapped statement的缓存。每一个查询mapped statement可以使用不同或相同的cacheModel。详细讨论见后面的章节,以下只给出个例子。
<cacheModel id="product-cache" imlementation="LRU"><flushInterval hours="24"/><flushOnExecute statement="insertProduct"/><flushOnExecute statement="updateProduct"/><flushOnExecute statement="deleteProduct"/><property name=”size” value=”1000” /></cacheModel><statement id=”getProductList” parameterClass=”int” cacheModel=”product-cache”> select * from PRODUCT where PRD_CAT_ID = #value#
</statement>上面例子中,“getProductList”的缓存使用WEAK引用类型,每24小时刷新一次,或当更新的操作发生时刷新。 关于ibatis补充说明<cacheModel id="oneday_cache" type="LRU" readOnly="false" serialize="true"> <flushInterval hours="24"/> <flushOnExecute statement="updateMyDate"/> <property name="size" value="200"/></cacheModel> 1 属性readOnly如果不写,默认是true,这时的缓存效果无疑最好,因为系统不需要考虑更新操作引起缓存与实际数据不一致的问题,只读缓存的例子是固化到数据库中的一些配置参数表。但是,通常我们想缓存的数据是需要增删改的,这时务必记得要加上 readOnly = "false";2 属性serialize,如果不写,默认为false, 将它设为true,可以提高整体应用(而不仅仅是每个Session)的性能。 这种缓存为每一个Session返回缓存对象不同的实例(复本)。因此每一个Session都可以安全修改返回的对象. 注意,此时readOnly必须为false。 如果你把它设为 true ,记得检查两件事,一件事是缓存中存放的对象(你想查询的POJO)必须是可序列化的, 即实现Serializable接口。如果你有一个复杂对象属性,它也必须满足这个规则,你的整个对象树必须是可序列化的。 另一件事是关闭sql-map-config中的延迟加载属性,即lazyload=false,原因是,它使用了动态代理机制, 那个代理对象并不是Serializable的。 缓存类型的最佳适应情形:MEMORY 没有统一的对象重用模式的应用,或内存不足的应用。
LRU 在较长的期间内,用户经常使用某些特定对象。 FIFO 用户在短时间内持续引用特定的查询,而后很可能不再使用。 根据个人实践,内存充足时使用LRU,否则使用MEMORY(WEAK)通常能获得较好的效果。※《ibatis开发指南》有关于上面几种缓存类型的详细说明。
<cacheModel type="OSCACHE" id="cache">
<flushInterval hours="24"/> <flushOnExecute statement="WapIndex.delete"/> <flushOnExecute statement="WapIndex.update"/> <property value="100" name="size"/></cacheModel>2007-7-9 11:45:42 IBatis中的强制刷新缓存 目前我们采用IBatis作ORM, 所以我们直接使用了IBatis 自带的缓存解决方案。当然你也可以定制,我在我的一篇文章可复用、扩展的缓存设计方案也谈到了如何定制 ,个人认为如果不是非常复杂的需求,完全可以借助ORM自带的方案.你会发现非常非常简单.
下面我们进入实战:
step1)写ibatis的相关配置
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"""><sqlMap namespace="specialtopic">
............
<cacheModel id="getTopVideoListByColumn1-cache" type ="OSCACHE" > <flushInterval seconds="60"/> </cacheModel> ............ <statement id="getTopVideoListByColumn1" resultMap="top-Video-column1" cacheModel="getTopVideoListByColumn1-cache"> select v.videoId,v.title,v.timeSpan,tu.loginName,vr.viewedCount from top_baby_video tbv inner join video v on tbv.videoId=v.videoId inner join video_report vr on v.videoId=vr.videoId inner join tvUser tu on v.tvUserId=tu.tvUserId </statement> </sqlMap> 显而易见上面的cacheModel是缓存策略, 只需加在statement段的属性中即可step2)写dao方法
public List getTopVideoListByColumn1 ()...{ List list = this.getSqlMapClientTemplate().queryForList("getTopVideoListByColumn1", null); return list; }就是这么简单,从客户端的角度看,缓存是透明的.你可以从配置文件修改你的缓存策略,不会对你的java代码造成任何影响.
强制刷新缓存的功能,如何实现?马上进入实战:
我们通过一个jsp搞定<%@ page import="xxx.common.utils.SpringBeanProxy"%>
<%@ page import="com.ibatis.sqlmap.client.SqlMapClient"%><% String cacheModelId = request.getParameter("cacheModelId"); SqlMapClient client = (SqlMapClient) SpringBeanProxy .getBean("sqlMapClient"); client.flushDataCache(cacheModelId);%>ok!
首先我们获取需要刷新缓存的id,然后从spring工厂中取出SqlMapClient ,然后利用SqlMapClient刷新缓存其实你也可以调用client.flushDataCache(),这样就刷新了所有的缓存模型而不是某一个.