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配置ehcacheEhcache配置文件爲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:表示對象永不過時,若是選true則5,6兩項無效。 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緩存的做用主要是在內存中保存某個具體對象,當用戶第一次經過get、iterator方式取出對象時,系統會先從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語句來修改數據庫相關記錄,那麼將對二級緩存的數據不會形成影響,換句話說,緩存中的對象數據將和數據庫中的不一致。 |