天天看點

hibernate回顧之緩存機制-一級緩存、二級緩存、查詢緩存

     在介紹hibernate的緩存機制前,我們先了解一下什麼是緩存:

     緩存(Cache): 計算機領域非常通用的概念。裡面放東西,說白了緩存就是一個集合。它介于應用程式和永久性資料存儲源(如硬碟上的檔案或者資料庫)之間,其作用是降低應用程式直接讀寫永久性資料存儲源的頻率,進而提高應用的運作性能。緩存中的資料是資料存儲源中資料的拷貝并且緩存的實體媒體通常是記憶體。

    了解jdbc的人都知道,當需要連接配接資料庫時,一般都會做一個連接配接池,那麼連接配接池和緩存有什麼差別呢?

    相同點:兩者都可以是在記憶體裡,實作時一樣的,都是為了提高性能的。

    不同點:連接配接池是一個重量級的池子,也就是說池子裡面的資源是很寶貴的東西。

    下面我們來了解一下hibernate中的緩存機制:一級緩存、二級緩存、查詢緩存。

一級緩存:

     1、在hibernate中,一個線程對應一個session,一個線程可以看成是一個session,也就是說session是和線程綁定在一起的。

     2、了解一級緩存:

       在session接口中包含了一系列的java接口,這些java集合構成了session級别的一級緩存,隻要是session執行個體的生命周期沒有結束,存放在其中的緩存對象就不會死亡。iterate、load、get、save等都使用使用一級緩存。

     3、一級緩存的清理

      session具有一個緩存,位于緩存中的對象稱為持久化對象,他和資料庫中的相關記錄對應,session在某些時間點,按照緩存中對象的變化來執行相關的sql語句,來同步更新資料庫,這一過程稱為清理緩存,預設情況下session在以下時間點清理緩存:

     (1)送出事務的時候,會先清理緩存session.flush();

     (2)緩存中的持久化對象發生變化,會先清理緩存以保證持久化對象的最新狀态。

     (3)顯示調用session.flush();

      清理相關的知識點:

      session.flush();會清理緩存,緩存中德持久化對象不會丢失,會産生insert語句。

      session.clear()清空緩存,緩存中的持久化對象丢失。

      session.reflush()讓session和資料庫同步,執行查詢,把資料庫的最新資訊顯示出來,更新本地緩存的對象狀态.。

      當session加載了一個對象後,回味該對象的值類型的屬性複制一份快照,當清理緩存時,通過比較對象的目前屬性和快照,來判斷對象的那些屬性發生了變化,

發生變化的執行sql語句,沒有變化的不執行sql語句。。

      在不使用refresh等的情況下,清理緩存時,要讓一級緩存中的對象和快照中的對象進行對比,不同的話在送出的時候會産生updata語句。

    4、其他知識點

      iter = session.createQuery("from Student s where s.id<5").iterate();

      while (iter.hasNext()) {

          Student student = (Student)iter.next();

          System.out.println(student.getName());

      iterate在沒有使用緩存的情況下會有n+1的問題。

      第一次iterate查詢會發出N+1條sql語句,第一條sql語句查詢所有的id,然後根據id查詢實體對象,有N個id就發出N條語句查詢實體。

      iterate查詢不同的屬性,一級緩存不會緩存,因為一級緩存是用來緩存實體對象的。

      session間不能共有一級緩存,一級緩存會伴随着session的消亡而失效。

二級緩存:

    1、二級緩存需要sessionFactory來管理,是程序級别的緩存,所有人都可以使用,是共享的。

    2、二級緩存比較複雜,一般用第三方的産品,hibernate隻提供了一個簡單的實作,用hashtable實作的。

    3、使用場合:長時間不改變的資料。

    4、配置步驟:

      (1)ehcache.xml 可以設定預設的,所有的類都遵循這個配置,也可以對某個對象單獨的配置。

      (2)在hibernate.cfg.xml配置檔案配置緩存,讓hibernate知道我們使用的是那個二級緩存。包括配置屬性:是否啟用二級緩存、二級緩存的提供商。

      (3)手動指定哪些實體類的對象放到緩存,在hibernate.cfg.xml配置

            <class-cache class="com.bjpowernode.hibernate.Student"  usage="read-only"/>

          或者

            在映射檔案中的id标簽前面<cache usage="read-only"/>

          usage屬性表示使用緩存的政策,一般優先使用read-only,表示如果資料放到緩存,就不能再修改了,因為經常修改的資料也不需要放到緩存中。

          read-only政策效率好,因為不能改緩存,但是可能出現髒資料的問題,這個問題的解決方案隻能依賴緩存的逾時,因為可能對象的資料被修改了,但是

      緩存卻沒有變,這樣造成資料不同步,也就是髒資料的問題。

          read-write當持久化對象發生變化時,緩存裡面就會跟着變化,資料庫中也改變了,這種方式需要加上鎖,效率比read-only慢。

    5、知識點:

         二級緩存必須讓sessionfactory管理,讓sessionfactory來清除,可以調用evict方法。

         查詢資料後會預設放到二級和一級緩存中,我們也可以控制查詢出來的資料不放到緩存裡面的,就是說我們可以控制一級緩存和二級緩存的交換。

       session.setCacheMode(CacheMode.IGNORE);禁止将一級緩存中的資料往二級緩存裡放。

         和一級緩存一樣,二級緩存也不存放普通屬性的查詢資料,這和一級緩存是一樣的,隻存放實體對象。

         session級别的緩存對性能提高沒有太大的意義,因為生命周期太短了。

查詢緩存:

   1、 一級緩存和二級緩存都隻是存放實體對象的,如果查詢實體對象的普通屬性的資料,隻能放到查詢緩存裡面,查詢緩存還存放查詢實體對象的id。

   2、查詢緩存的生命周期不确定,當它關聯的表發生修改時(通過hibernate),查詢緩存的生命周期就結束。

   3、查詢緩存預設是關閉的,可以在hibernate.cfg.xml配置<property name="hibernate.cache.use_query_cache">true</property>。并且必須在程式中手動啟動查詢緩存,在query接口中的setCacheable(true)方法來啟用。

   4、查詢緩存意義不是很大,查詢緩存說明白了就是存放由list方法或者iterate方法查詢的資料,我們在查詢時很少出現完全相同的條件查詢,這就是說命中率低,

這樣的緩存裡的資料總是變化的。除非多次查詢都是查詢相同條件的資料,也就是說傳回的結果總是一樣,這樣的緩存配置才有意義。

繼續閱讀