最近看了查询缓存的2篇文章,特别有感悟,所以特别研究了下hibernate3源码,有了一点小小收获,所以这里总结一下
有2篇关于查询缓存的好文,这里推荐一下,感谢作者分享这么好的东西
数据库对象的缓存策略
http://www.iteye.com/topic/9706
偶来谈谈Hibernte 的QueryCache。
http://www.iteye.com/topic/10537
上面2篇文章都讲的是hibernate2的Query缓存策略,这里我详细讲解下Hibernate3的Query缓存策略,与《数据库对象的缓存策略》一文中提到的Hibernate2有所区别,与Jive的缓存策略相似,但针对ID查询不再去查询数据库,而是ID缓存中读取数据对象
Hibernate3的Query缓存策略
1.Hibernate的Query缓存策略的过程描述:
(1) 条件查询的请求一般都包括如下信息:SQL, SQL需要的参数,记录范围(起始位置rowStart,最大记录个数maxRows),等。
(2) Hibernate首先根据这些信息组成一个Query Key,根据这个Query Key到Query缓存中查找对应的结果列表。如果存在,那么返回这个结果列表;如果不存在,查询数据库,获取结果列表,把整个结果ID列表根据Query Key放入到Query缓存中,再将每个ID对应的结果存放在配置的ID查询缓存中
(3) Query Key中的SQL涉及到一些表名,如果这些表的任何数据发生修改、删除、增加等操作,这些相关的Query Key都要从缓存中清空。
2.Hibernate的Query缓存策略的优点
(1) 条件查询的时候,如果Query Key已经存在于缓存,那么不需要再查询数据库。命中的情况下,一次数据库查询也不需要。
3.Hibernate的Query缓存策略的缺点
(1) 条件查询涉及到的表中,如果有任何一条记录增加、删除、或改变,那么缓存中所有和该表相关的Query Key都会失效。
比如,有这样几组Query Key,它们的SQL里面都包括table1。
SQL = select * from table1 where c1 = ? …., parameter = 1, rowStart = 11, maxRows = 20.
SQL = select * from table1 where c1 = ? …., parameter = 1, rowStart = 21, maxRows = 20.
SQL = select * from table1 where c1 = ? ….., parameter = 2, rowStart = 11, maxRows = 20.
SQL = select * from table1 where c1 = ? ….., parameter = 2, rowStart = 11, maxRows = 20.
SQL = select * from table1 where c2 = ? …., parameter = ‘abc’, rowStart = 11, maxRows = 20.
当table1的任何数据对象(任何字段)改变、增加、删除的时候,这些Query Key对应的结果集都不能保证没有发生变化。
很难做到根据数据对象的改动精确判断哪些Query Key对应的结果集受到影响。最简单的实现方法,就是清空所有SQL包含table1的Query Key。
(2) Query缓存中,Query Key对应的是数据对象列表,假如不同的Query Key对应的数据对象列表有交集,那么,交集部分的数据对象不是重复存储的,只是ID重复存储,这与hibernate2完全不同,这也是hibernate3的改进之处
比如,Query Key 1对应的数据对象列表为{a(id = 1), b(id = 2)},Query Key 2对应的数据对象列表为{a(id = 1), c(id = 3)},这个a的ID存了2份,但是ID对应的数据对象只存了一份
下面我讲下如何使用
我这里使用的是二级缓存ehcahce,配置如下:
ehcache.xml
<!-- hibernate默认的查询缓存配置 -->
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="10000"
timeToLiveSeconds="10000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
<!-- ID查询缓存配置,其实就是针对com.tukechina.mms.pojos.Business对象的缓存策略 -->
<cache name="com.tukechina.mms.pojos.Business"
maxElementsInMemory="10000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="10000"
timeToLiveSeconds="10000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
ID查询缓存还需要在Business.hbm.xml文件中加入缓存配置,如下
<hibernate-mapping>
<class name="com.tukechina.mms.pojos.Business" table="business" catalog="tuke_mmsmsys">
<!-- 设置该持久化类的二级缓存并发访问策略 read-only read-write nonstrict-read-write transactional-->
<cache usage="read-write"/>
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="identity" />
</id>
<property name="nameCh" type="string">
<column name="name_ch" length="50" not-null="true" />
</property>
<property name="nameEn" type="string">
<column name="name_en" length="50" not-null="true" />
</property>
<property name="level" type="int">
<column name="level" not-null="true" />
</property>
<property name="productId" type="int">
<column name="product_id" not-null="true" />
</property>
<property name="cp" type="int">
<column name="cp" not-null="true" />
</property>
<property name="description" type="string">
<column name="description" length="65535" />
</property>
<property name="code" type="int">
<column name="code" not-null="true" />
</property>
<property name="insertTime" type="timestamp">
<column name="insert_time" length="0" />
</property>
<property name="status" type="int">
<column name="status" not-null="true" />
</property>
<property name="endTime" type="timestamp">
<column name="end_time" length="0" />
</property>
<property name="cooperateWay" type="string">
<column name="cooperate_way" length="50" />
</property>
<property name="incomeDivideWay" type="string">
<column name="income_divide_way" length="50" />
</property>
<property name="area" type="string">
<column name="area" length="50" />
</property>
<property name="areacode" type="string">
<column name="areacode" length="10" />
</property>
<property name="updateTime" type="timestamp">
<column name="update_time" length="0" />
</property>
<property name="sendType" type="int">
<column name="send_type" not-null="true" />
</property>
<property name="sendId" type="java.lang.Integer">
<column name="send_id" />
</property>
</class>
</hibernate-mapping>
最后是在Query执行代码中要加上setCacheable(true)设置应用缓存策略
MmsSendStatDAOForMYSQL4.java
String bqueryString = "select a from "
+ Business.class.getName() + " a";
if (admin.getType() != 0) {// 判断管理员权限
bqueryString += ","
+ RelevantAuthority.class.getName()
+ " b where a.status!=2 and a.id = b.relatedId and b.type=4 and b.account='"
+ admin.getAccount() + "'";
} else {
bqueryString += " where a.status!=2 ";
}
Query bquery = s.createQuery(bqueryString);
//设置缓存应用
bquery.setCacheable(true);
//bquery.setCacheMode(CacheMode.GET);
List<Business> blist = bquery.list();
执行以上程序,打开log4j日志为debug级别查看缓存是否应用
log4j.logger.org.hibernate.cache.StandardQueryCache = debug
日志输出如下:
引用
DEBUG [http-8080-Processor22] (StandardQueryCache.java:104) - checking cached query results in region: org.hibernate.cache.StandardQueryCache
DEBUG [http-8080-Processor22] (StandardQueryCache.java:162) - Checking query spaces for up-to-dateness: [tuke_mmsmsys.business]
DEBUG [http-8080-Processor22] (StandardQueryCache.java:119) - returning cached query results
分享到:
相关推荐
讲解如何使用HQL,包括基本的操作和进阶用的高级使用
源码 博文链接:https://raymondhekk.iteye.com/blog/250427
本光盘是《整合Struts+Hibernate+Spring应用开发详解》一书的配书光盘,书中的代码按章存放, 即第二章所使用的代码放在codes文件夹的02文件夹下,依次类推。 本光盘根目录下有11个文件夹,其内容和含义说明如下: ...
帮助学生理解掌握使用Query接口的绑定参数的使用方式及其含义
本光盘是《整合Struts+Hibernate+Spring应用开发详解》一书的配书光盘,书中的代码按章存放, 即第二章所使用的代码放在codes文件夹的02文件夹下,依次类推。 本光盘根目录下有11个文件夹,其内容和含义说明如下: ...
Hibernate第3版开发手册详解.pdf
整合struts+hibernate+spring应用开发详解 李刚 第二到第四章
Hibernate3技术精辟详解 Hibernate3 Hibernate3详解,看过就知道Hibernate3怎么配置和应用
hibernate cache
hibernate 二级缓存详解hibernate 二级缓存详解hibernate 二级缓存详解hibernate 二级缓存详解hibernate 二级缓存详解hibernate 二级缓存详解hibernate 二级缓存详解hibernate 二级缓存详解hibernate 二级缓存详解
Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法 Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法 Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法 Hibernate SQL...
hibernate包详解+hibernatePPThibernate包详解+hibernatePPThibernate包详解+hibernatePPT
Hibernate详解,为你打开Hibernate使用的底层框架。
Hibernate缓存深入详解
hibernate的配置介绍,在myeclipse中配置hibernate,hibernate已经在myeclipse中了,创建工程,然后在工程中添加hibernate框架,一些设置
Hibernate_配置映射文件详解