`
badboy_990726
  • 浏览: 11953 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

hibernate3的QueryCache使用详解

阅读更多
最近看了查询缓存的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
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics