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();


转载于:https://my.oschina.net/u/2004668/blog/354990

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值