您的位置:首页 > 其它

hibernate查询缓存和二级缓存详解

2014-12-11 00:00 357 查看
摘要: hibernate查询缓存和二级缓存详解

本文介绍hibernate的查询缓存以及二级缓存,如何配置,以及他们的工作原理。

概要

hibernate二级缓存是用来存储实体数据的应用级缓存,而查询缓存是用来只存储查询结果的单独的缓存。这两种缓存通常是一起发挥着作用,毕竟我们很少见到只使用其中一种缓存的场景,hibernate Cahce通过减少sql对数据库的访问数量来提高程序的性能。

二级缓存工作原理

二级缓存存储的是实体数据,而不是实体本身,数据是以一种类似HashMap的key-value格式存储的,key就是实体的id,value就是原始值的集合,二级缓存中的内容如下所示:

*-----------------------------------------*
|          Person Data Cache              |
|-----------------------------------------|
| 1 -> [ "John" , "Q" , "Public" , null ] |
| 2 -> [ "Joey" , "D" , "Public" ,  1   ] |
| 3 -> [ "Sara" , "N" , "Public" ,  1   ] |
*-----------------------------------------*


当通过id从数据库中获取一个对象,或者遍历延迟加载的映射关系时,获取到的对象将填充到二级缓存中。

查询缓存工作原理

查询缓存也是一种类似于HashMap的结构,key由查询语句和参数组成,value是和查询语句相匹配的实体Id的集合:

*----------------------------------------------------------*
|                       Query Cache                        |
|----------------------------------------------------------|
| ["from Person where firstName=?", ["Joey"] ] -> [1, 2] ] |
*----------------------------------------------------------*


某些查询不会返回实体,而返回原始值,这种情况下,原始值将被存入查询缓存。当执行可缓存的JPQL/HQL查询时,查询结果才能存入查询缓存中。

查询缓存和二级缓存之间的关系

如果将要被执行的查询之前已经有缓存的结果集,SQL语句将不会再去访问数据库,而是直接从查询缓存中获取查询结果,然后通过结果集中的实体标示符(ID)去访问二级缓存,如果二级缓存中包含指定id的数据,则返回该数据对应的实体,否则,再去数据库查询获取该实体。

如何在程序中使用Cache

先导入hibernate-ehcache.jar

然后在SessionFactory配置文件中加入下列属性

<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
<prop key="net.sf.ehcache.configurationResourceName">ehcache-ext.xml</prop>


使用EhCacheRegionFactory代替SingletonEhCacheRegionFactory,然后Hibernate将会为它创建独立的缓存区,而不是重复利用程序中其他地方已经存在的缓存区。

接下来添加缓存配置文件

<?xml version="1.0" ?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
updateCheck="false"
xsi:noNamespaceSchemaLocation="ehcache.xsd" name="yourCacheManager">

<diskStore path="java.io.tmpdir"/>

<cache name="yourEntityCache"
maxEntriesLocalHeap="10000"
eternal="false"
overflowToDisk="false"
timeToLiveSeconds="86400" />

<cache name="org.hibernate.cache.internal.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false
timeToLiveSeconds="86400"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU" />

<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToLiveSeconds="86400"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU" /></ehcache>


如果没有指定,则使用默认的缓存,但是尽量避免使用默认的配置,最后确保每个ehcache元素都有name属性,这样可以防止他使用默认的名称,以免和其他配置引起冲突。

使用二级缓存

为了能让缓存发挥作用,首先必须在实体类上加上注解:

@Entity
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY,
region="yourEntityCache")
public class SomeEntity {
...
}


二级缓存也可以缓存关联的实体,但是必须在关联实体上也要加注解:

@Entity
public class SomeEntity {
@OneToMany
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY,
region="yourCollectionRegion")
private Set<OtherEntity> other;
}


使用查询缓存

配置好查询缓存之后,默认情况下查询还不能被缓存,还必须使用缓存明确的标注查询。如下的查询被标注为缓存

@NamedQuery(name="account.queryName",
query="select acct from Account ...",
hints={
@QueryHint(name="org.hibernate.cacheable",
value="true")
}
})


将Criteria Query标注为缓存:

List cats = session.createCriteria(Cat.class)
.setCacheable(true)
.list();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate 缓存 详解