<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Thinking

    快樂編程,開心生活
    posts - 21, comments - 27, trackbacks - 0, articles - -5
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    Cache的層次

    Posted on 2007-02-06 17:31 lixw 閱讀(636) 評論(0)  編輯  收藏

    1、查詢緩存

    ? 首先需要配置hibernate.cache.use_query_cache=true

    如果用ehcache,配置ehcache.xml,注意hibernate3.0以后不是net.sf的包名了

    ?1?<cache?name="net.sf.hibernate.cache.StandardQueryCache"
    ?2?
    ?3?maxElementsInMemory="50"?eternal="false"?timeToIdleSeconds="3600"
    ?4?
    ?5?timeToLiveSeconds="7200"?overflowToDisk="true"/>
    ?6?
    ?7?<cache?name="net.sf.hibernate.cache.UpdateTimestampsCache"
    ?8?
    ?9?maxElementsInMemory="5000"?eternal="true"?overflowToDisk="true"/>
    10?
    11?

    ? 然后

    query.setCacheable(true);//激活查詢緩存

    query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion,可選

    第二行指定要使用的cacheRegion是myCacheRegion,即你可以給每個查詢緩存做一個單獨的配置,

    使用setCacheRegion來做這個指定,需要在ehcache.xml里面配置它:

    1 < cache? name ="myCacheRegion" ?maxElementsInMemory ="10" ?eternal ="false"
    2
    3 timeToIdleSeconds ="3600" ?timeToLiveSeconds ="7200" ?overflowToDisk ="true" ? />
    4
    5


    如果省略第二行,不設置cacheRegion的話,那么會使用上面提到的標準查詢緩存的配置,也就是

    net.sf.hibernate.cache.StandardQueryCache

    ? 問題:當hibernate更新數據庫的時候,它怎么知道更新哪些查詢緩存呢?

    ??? hibernate在一個地方維護每個表的最后更新時間,其實也就是放在上面

    net.sf.hibernate.cache.UpdateTimestampsCache所指定的緩存配置里面。

    當通過hibernate更新的時候,hibernate會知道這次更新影響了哪些表。然后它更新這些表的最后更新時間。每個緩存都有一個生成時間和這個緩存所查詢的表,當hibernate查詢一個緩存是否存在的時候,如果緩存存在,它還要取出緩存的生成時間和這個緩存所查詢的表,然后去查找這些表的最后更新時間,如果有一個表在生成時間后更新過了,那么這個緩存是無效的。可以看出,只要更新過一個表,那么凡是涉及到這個表的查詢緩存就失效了,因此查詢緩存的命中率可能會比較低。

    ? 注意:

    ??? 放入緩存中的key是查詢的語句,value是查詢之后得到的結果集的id列表。

    表面看來這樣的方案似乎能解決hql利用緩存的問題,但是需要注意的是,構成key的是:

    hql生成的sql、sql的參數、排序、分頁信息等。也就是說如果你的hql有小小的差異,

    比如第一條hql取1-50條數據,第二條hql取20-60條數據,那么hibernate會認為這是兩個

    完全不同的key,無法重復利用緩存。因此利用率也不高。

    ?? 查詢緩存必須配合二級緩存一起使用,否則極易出現1+N的情況

    ?? 如果不設置"查詢緩存",那么hibernate只會緩存使用load()方法獲得的單個持久化對象,

    如果想緩存使用findall()、list()、Iterator()、createCriteria()、createQuery()等方法

    獲得的數據結果集的話,就需要設置hibernate.cache.use_query_cache true才行,如果需要"查詢緩存",需要在使用Query或Criteria()時設置其setCacheable(true);屬性。?
    2、Collection緩存

    ? 需要在hbm的collection里面設置

    < cache? usage ="read-write" />

    假如class是Cat,collection叫children,那么ehcache里面配置

    1 < cache? name ="com.xxx.pojo.Cat.children"
    2
    3 maxElementsInMemory ="20" ?eternal ="false" ?timeToIdleSeconds ="3600"
    4
    5 timeToLiveSeconds ="7200"
    6
    7 overflowToDisk ="true" ? />
    8

    Collection的緩存和前面查詢緩存的list一樣,也是只保持一串id,但它不會因為這個表更新過就

    失效,一個collection緩存僅在這個collection里面的元素有增刪時才失效。

    這樣有一個問題,如果你的collection是根據某個字段排序的,當其中一個元素更新了該字段時,

    導致順序改變時,collection緩存里面的順序沒有做更新?
    3、Class緩存(也稱二級緩存)

    ?? 可由Hibernate提供的二級緩存實現,它存在于SessionFactory級別,

    緩存結構可以看作是一個hash table,key是數據庫記錄的id,value是id對應的pojo對象。

    當用戶根據id查詢對象的時候(load、iterator方法),會首先在緩存中查找,

    如果沒有找到再發起數據庫查詢。但是如果使用hql發起查詢(find, query方法)

    則不會利用二級緩存,而是直接從數據庫獲得數據,但是它會把得到的數據放到二級緩存備用。也就是說,基于hql的查詢,對二級緩存是只寫不讀的。?
    在hibernate.cfg.xml配置:

    < property? name ="hibernate.cache.provider_class" >

    ???????org.hibernate.cache.EhCacheProvider

    </ property >

    hibernate3支持

    Hashtable Cache(org.hibernate.cache.HashtableCacheProvider)

    EhCache(org.hibernate.cache.EhCacheProvider)

    OSCache(org.hibernate.cache.OSCacheProvider)

    SwarmCache(org.hibernate.cache.SwarmCacheProvider)

    JBossCache(org.hibernate.cache.TreeCacheProvider)

    在相應的POJO配置文件中增加:

    <!--

    指定緩存同步策略:

    read-write???????????????????????????讀寫型

    nonstrict-read-write?????????????非嚴格讀寫型

    read-only?????????????????????????? ?只讀型

    transactional??????????????????????? 事務型

    -->

    <cache usage="read-write"/>?

    Cache read-only nonstrict-read-write read-write transactional
    EhCache Yes Yes Yes No
    OSCache Yes Yes Yes No
    SwarmCache Yes Yes No No
    TreeCache Yes No No Yes

    ?????對于一條記錄,也就是一個PO來說,是根據ID來找的,緩存的key就是ID,value是POJO。無論

    list,load還是iterate,只要讀出一個對象,都會填充緩存。但是list不會使用緩存,而iterate

    會先取數據庫select id出來,然后一個id一個id的load,如果在緩存里面有,就從緩存取,沒有

    的話就去數據庫load。

    ?? 當某個ID通過hibernate修改時,hibernate會知道,于是移除緩存。

    這樣大家可能會想,同樣的查詢條件,第一次先list,第二次再iterate,就可以使用到緩存了。

    實際上這是很難的,因為你無法判斷什么時候是第一次,而且每次查詢的條件通常是不一樣的,假

    如數據庫里面有100條記錄,id從1到100,第一次list的時候出了前50個id,第二次iterate的時候

    卻查詢到30至70號id,那么30-50是從緩存里面取的,51到70是從數據庫取的,共發送1+20條sql。

    所以我一直認為iterate沒有什么用,總是會有1+N的問題。 如果想要對list或者iterate查詢的結

    果緩存,就要用到查詢緩存了。?
    ? 注意:

    ?? 對于one-to-many的關聯關系,如果對one應用緩存,則應同時對many應用。

    ?? 二級緩存的失效機制由hibernate控制,當某條數據被修改之后,hibernate會根據它的id去做

    緩存失效操作。基于此機制,如果數據表不是被hibernate獨占,那么二級緩存無法得到有效控制

    ?? hibernate 3.0在做批量修改、批量更新的時候,是不會同步更新二級緩存的

    ?? 查詢緩存和二級緩存是有關聯關系的,他們不是完全獨立的兩套東西。假如一個查詢條件hql_1

    ,第一次被執行的時候,它會從數據庫取得數據,然后把查詢條件作為key,把返回數據的所有id

    列表作為value(請注意僅僅是id)放到查詢緩存中,同時整個結果集放到二級緩存,key是id,

    value是pojo對象。當你再次執行hql_1,它會從緩存中得到id列表,然后根據這些列表一個一個的

    到二級緩存里面去找pojo對象,如果找不到就向數據庫發起查詢。也就是說,如果二級緩存配置了

    超時時間,就有可能出現查詢緩存命中了,獲得了id列表,但是class里面相應的pojo已經因為超

    時被失效,hibernate就會根據id清單,一個一個的去向數據庫查詢,有多少個id,就執行多少個

    sql。該情況將導致性能下降嚴重。

    ?? 查詢緩存的失效機制也由hibernate控制,數據進入緩存時會有一個timestamp,它和數據表的

    timestamp對應。當hibernate環境內發生save、update等操作時,會更新被操作數據表的

    timestamp。用戶在獲取緩存的時候,一旦命中就會檢查它的timestamp是否和數據表的timestamp

    匹配,如果不,緩存會被失效。因此查詢緩存的失效控制是以數據表為粒度的,只要數據表中任何

    一條記錄發生一點修改,整個表相關的所有查詢緩存就都無效了。因此查詢緩存的命中率可能會很

    低。?
    4、對方法的緩存

    ? 對于調用頻率較高的查詢類方法,我們希望緩存方法結果

    在spring中可利用攔截器(Interceptor)實現,可能如下面的配置:

    ?1 < beans >
    ?2
    ?3 ???? < bean? id ="cacheInterceptor"
    ?4
    ?5 class ="org.springframework.aop.interceptor.cache.OSCacheInterceptor" >
    ?6
    ?7 ??????? <! -?默認刷新時間(秒)- >
    ?8
    ?9 ??????? < property? name ="defaultRefreshPeriod" >
    10
    11 ??????????? < value > 60 </ value >
    12
    13 ??????? </ property >
    14
    15 ??????? < property? name ="identifiers" >
    16
    17 ??????????? < props >
    18
    19 ?????????????? < prop? key ="java.util.Map" > toString </ prop >
    20
    21 ??????????? </ props >
    22
    23 ??????? </ property >
    24
    25 ???? </ bean >
    26
    27 ???? <! -?正則表達式匹配?- >
    28
    29 ???? < bean? id ="searcherAdvisor"
    30
    31 class ="org.springframework.aop.support.RegexpMethodPointcutAdvisor" >
    32
    33 ??????? < property? name ="advice" >
    34
    35 ??????????? < ref? local ="cacheInterceptor" ? />
    36
    37 ??????? </ property >
    38
    39 ??????? < property? name ="patterns" >
    40
    41 ??????????? < list >
    42
    43 ?????????????? < value > .get. </ value >
    44
    45 ??????????? </ list >
    46
    47 ??????? </ property >
    48
    49 ???? </ bean >
    50
    51 ???? <! -?自動代理?- >
    52
    53 ???? < bean? id ="proxyCreator1"
    54
    55 class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
    56
    57 ??????? < property? name ="beanNames" >
    58
    59 ?????????? <!-- ?需截獲方法的bean列表? -->
    60
    61 ??????????? < list >
    62
    63 ?????????????? < value > commonSelect </ value >
    64
    65 ??????????? </ list >
    66
    67 ??????? </ property >
    68
    69 ??????? < property? name ="interceptorNames" >
    70
    71 ?????????? <!-- ?截獲器列表? -->
    72
    73 ??????????? < list >
    74
    75 ?????????????? < value > searcherAdvisor </ value >
    76
    77 ??????????? </ list >
    78
    79 ??????? </ property >
    80
    81 ???? </ bean >
    82
    83 < beans >
    84
    85

    ?這里通過自動代理創建bean,并指定作用其上的interceptor列表,在commonSelect存在searchAdvisor,

    而searchAdvisor對匹配*get*模式的方法調用將通過cacheInterceptor進行處理。


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲精品国产V片在线观看| 欧美大尺寸SUV免费| 亚洲avav天堂av在线网爱情| 最新亚洲成av人免费看| 老司机亚洲精品影视www| rh男男车车的车车免费网站| 亚洲情侣偷拍精品| 丝瓜app免费下载网址进入ios| 国产亚洲精品精品国产亚洲综合| igao激情在线视频免费| 综合亚洲伊人午夜网 | 18观看免费永久视频| 久久精品国产精品亚洲毛片| 亚洲黄色免费观看| 亚洲综合激情五月色一区| 日本最新免费不卡二区在线| 最新亚洲人成无码网站| 亚洲高清无码在线观看| 天堂在线免费观看| 亚洲特级aaaaaa毛片| g0g0人体全免费高清大胆视频| 亚洲日产韩国一二三四区| 蜜臀98精品国产免费观看| 亚洲人成电影网站色| 亚洲欧洲自拍拍偷精品 美利坚| 国产在线观看免费av站| 91嫩草亚洲精品| 国产一区视频在线免费观看| 99免费在线视频| 亚洲av无码一区二区三区天堂古代| 日本免费网站在线观看| 国产一区二区免费视频| 亚洲中文字幕无码一去台湾| 亚洲精品动漫人成3d在线| 18女人毛片水真多免费| 美美女高清毛片视频黄的一免费| 亚洲精品无码不卡在线播HE| 岛国av无码免费无禁网站| 国产成人无码精品久久久免费 | 国产亚洲精品成人AA片| 亚洲&#228;v永久无码精品天堂久久|