Hibernate二級緩存的使用



 

1啓用Hibernate二級緩存

Hibernate二級緩存分爲兩部分,class緩存和查詢緩存,其獲取對象的方式有所不一樣,但二者也有聯繫,查詢緩存必須以class緩存爲基礎才能起做用,不然只會使效率更低。java

咱們這裏使用的二級緩存是經過ehcache第三方插件實現的。spring

1.1配置Hibernate.cfg.xml

啓用class緩存:sql

              <property name="hibernate.cache.provider_class">數據庫

                     org.hibernate.cache.EhCacheProvider緩存

              </property>session

       啓用查詢緩存:框架

              <property name="hibernate.cache.use_query_cache">true</property>ide

1.2配置Spring框架中的hibernate

       啓用class緩存:spa

<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>hibernate

啓用查詢緩存:

<prop key="hibernate.cache.use_query_cache">true</prop>

1.3配置ehcache

       Ehcache配置文件爲ehcache.xml,默認配置爲:

              <ehcache>

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

                  <defaultCache

                   maxElementsInMemory="10000"

                   eternal="false"

                   timeToIdleSeconds="1800"

                   timeToLiveSeconds="1800"

                   overflowToDisk="true"

            />

</ehcache>

       其中各項內容的含義爲:

1         diskStore:表明當二級緩存對象數據在內存中溢出,若是須要寫入文件系統時的文件目錄。

2         defaultCache:默認的calss緩存配置,若是某個對象沒有其專有的配置時,ehcache一概啓用默認配置。

3         maxElementInMemory:對象在內存中可存放的最大數量。

4         eternal:表示對象永不過時,若是選true56兩項無效。

5         timeToIdleSeconds:對象的空閒狀態過時時間,單位爲秒,0爲能夠無限制空閒。

6         timeToLiveSeconds:對象存在的最長時間,單位爲秒(注意,若是該項比5項要小,則第5項無心義),0爲永不過時。

7         overflowToDisk:當對象在內存中的數量超過maxElementInMemory值時,若是該項爲true,則ehcahe會把對象數據寫入diskStore項指定的目錄。

若是須要對某個具體對象進行單獨配置時,能夠加上一組cache配置,例如:

            <cache name="com.juyee.mp.bean.SysCodelist"

            maxElementsInMemory="10000"

            eternal="true"

            timeToIdleSeconds="1800"

            timeToLiveSeconds="0"

            overflowToDisk="true"

         />

另外還有兩個特殊的cache配置:

     <cache name="org.hibernate.cache.UpdateTimestampsCache"

            maxElementsInMemory="5000"

            eternal="true"

            timeToIdleSeconds="1800"

            timeToLiveSeconds="0"             

            overflowToDisk="true"/>

     <cache name="org.hibernate.cache.StandardQueryCache"

            maxElementsInMemory="10000"

            eternal="false"

            timeToIdleSeconds="1800"

            timeToLiveSeconds="0"

            overflowToDisk="true"/>

這兩個cache配置對應查詢緩存,具體做用以下(摘用別人的描述):

       「當hibernate更新數據庫的時候,它怎麼知道更新哪些查詢緩存呢? hibernate在一個地方維護每一個表的最後更新時間,其實也就是放在上面UpdateTimestampsCache所指定的緩存配置裏面。

當經過hibernate更新的時候,hibernate會知道此次更新影響了哪些表。而後它更新這些表的最後更新時間。每一個緩存都有一個生成時間和這個緩存所查詢的表,當hibernate查詢一個緩存是否存在的時候,若是緩存存在,它還要取出緩存的生成時間和這個緩存所查詢的表,而後去查找這些表的最後更新時間,若是有一個表在生成時間後更新過了,那麼這個緩存是無效的。

能夠看出,只要更新過一個表,那麼凡是涉及到這個表的查詢緩存就失效了,所以查詢緩存的命中率可能會比較低。」

       固然,若是沒有這兩個配置,則ehcache將爲查詢緩存啓用默認配置。

 

2如何使用class緩存

2.1對象緩存    

Class緩存的做用主要是在內存中保存某個具體對象,當用戶第一次經過getiterator方式取出對象時,系統會先從class緩存中去找,若是沒有再經過sql語句去數據庫中查找相關記錄,並將查詢到的對象放入內存中。

       實例:對某個對象使用二級緩存,只須要在該對象的hbm文件中配置便可

<cache usage="read-write"/>

       咱們注意到其中usage這個選項,它有多個選擇,對應不一樣的含義,常常有這兩種種:

1         read-only:只對緩存中的對象進行讀操做。

2         read-write:當對象被update時,緩存中和數據庫中一同被修改(緩存不支持事務回滾)。

2.2關聯緩存

目前咱們僅僅實現了對一個對象的緩存,那如何對該對象的關聯對象集合進行緩存呢?

實例:對某個對象的關聯對象集合的二級緩存,須要在該對象的hbm文件中set配置進行修改

              <set name="children" lazy="true" order-by="treeid asc">

            <cache usage="read-write"/>

                     <key column="PARENTID"/>

                     <one-to-many class="SysCodelist"/>

              </set>           

注意:

1         只對one-to-many有效,並且僅僅緩存的是關聯對象的id集合,若是須要實現徹底緩存,則須要對關聯的對象也配置成使用二級緩存。

2         集合緩存是獨立的,不受關聯對象添加、刪除的影響,若是要修改集合內容,必須對這個集合自己進行修改,例如:codelist.getChildren().add()

3如何使用查詢緩存

       查詢緩存,目的是爲了將經過list()方法的查詢結果存入緩存中,並實現對語句的緩存,若是下次用戶在使用這條語句進行查詢時,將直接從緩存中獲取對象數據。

       這裏要注意的是,查詢緩存必須配合class緩存使用,若是隻啓用查詢緩存,不對查詢對象啓用二級緩存,則會大大下降查詢效率。

由於,當第一次經過啓用查詢緩存的session進行語句查詢時,系統只執行一次數據庫查詢將全部的記錄取出,並將對象存入class緩存,語句及id集合存入查詢緩存;而當用戶第二次查詢該語句時,系統將先執行去查詢緩存中查找,取出全部符合條件的id集合,若是這時候該對象的class緩存沒啓用或在class緩存中已過時,系統將根據id,一個個去數據庫load,其實是進行了1+N次查詢。

實際上,在咱們系統中,並非對全部對象都要進行二級緩存,而spring框架中提供的hibernate方法,雖然有getHibernateTemplate().setCacheQueries(),但該方法影響的是全局的配置,一旦啓用,將會對不須要緩存的查詢形成不良影響。

因而,我本身在hibernateService()中添加了一個方法:

    public List findByCachedQuery(final String hql)

    {

        return (List) getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(Session session) throws HibernateException {

                Query queryObject = session.createQuery(hql);

                queryObject.setCacheable(true);

                if (getHibernateTemplate().getQueryCacheRegion() != null) {

                    queryObject.setCacheRegion(getHibernateTemplate().getQueryCacheRegion());

                }

                return queryObject.list();

            }

        }, true);

    }

這樣,將只在session範圍內啓用查詢緩存,一旦該session結束了,那麼查詢緩存也將回復默認配置。

注意:使用時只支持hql

4注意事項

       在使用二級緩存時,注意,全部對數據庫的修改都必須走hibernate,若是從其餘系統來或使用sql語句來修改數據庫相關記錄,那麼將對二級緩存的數據不會形成影響,換句話說,緩存中的對象數據將和數據庫中的不一致。

相關文章
相關標籤/搜索