Hibernate的一級快取Session和二級快取SessionFactory

陳俊成發表於2016-09-19

Hibernate的一級快取是指Session(屬於事務範圍的快取,由Hibernate管理,無需干預),它是一塊記憶體空間,用來存放相互管理的java物件,有了一級快取,應用程式可以減少訪問資料庫的次數,提高了效能。

在使用Hibernate查詢物件的時候,首先會使用物件屬性的OID值(對應表中的主鍵)在Hibernate的一級快取進行查詢,如果找到,則取出返回,不會再查詢資料庫,如果沒有找到,再到資料庫中進行查詢操作。然後將查詢結果存放到Session一級快取中。

特點:

  • 進行save()、update()、saveOrUpdate()操作的時候會把相應的物件那個存放在session快取中(注意,save()和update()並不是直接反應到資料庫中,而是反應到session中,當事務進行提交的時候,session會進行刷出操作,將session中物件的變化反映到資料庫中)
  • 呼叫get()、load()的時候或其他進行查詢的方法,會現在session中查詢,若有返回,若無,查詢資料庫,然後把結果儲存在session中
  • 當呼叫session的close()的時候,一級快取清空
  • Session會在某些時間點,按照快取中物件的變化進行資料庫的同步,如下幾種時間:
    (1)當應用程式呼叫Transaction的commit()方法時,該方法先刷出快取,然後再向資料庫提交事務
    (2)當應用程式執行一些查詢操作時,如果快取中持久化物件的屬性已經發生了變化,會先刷出快取,保證同步
    (3)手動執行session.flush()

Hibernate是如何實現一級快取的呢?
這是依賴了Hibernate快照來實現的,其實session與資料庫資料的對比並不是真正的對比,session不是和資料庫的資料做對比,而是和Hibernate快照做對比,但這個快照永遠和資料庫的資料保持一致。

Hibernate向以及快取放入資料時,同時賦值一份資料放入到Hibernate快照中,當使用commit()方法提交事務時,同時會清理Session的一級快取(flush操作,之後session清空),這是會使用OID判斷以及快取中的物件和快照中的物件是否一致,如果兩個物件中的屬性發生變化,則執行update語句,將快取的內容同步到資料庫中,並更新快照(從這裡可以知道資料庫和快照保持一致);如果一致,則不執行update語句。Hibernate快照的作用就是確保一級快取中的資料和資料庫中的資料一致。

一級快取的3個操作:

  • flush():同步後清空
  • clear():只是清空一級快取,並不會進行同步操作(session.evict(book):只對session中的某個物件進行清理操作)
  • refresh():重新整理操作,在refresh()操作前,程式設計師可以對從資料庫獲取的物件進行屬性修改,但是refresh()執行後,這些物件的屬性恢復原來的樣子。即:refresh()的作用是:使Hibernate快照區和一級快取中的資料域資料庫保持一致。

Hibernate的二級快取是SessionFactory,屬於程式範圍的快取。
SessionFactory的快取分為兩類:

  • 內建快取
    Hibernate自帶,不可解除安裝。在Hibernate的初始化階段,Hibernate會把對映後設資料(對映檔案中資料的賦值)和預定義的SQL語句放到SessionFactory的快取中。該內建快取是隻讀的。
  • 外接快取
    可配置的快取外掛。預設不會開啟,快取可以是記憶體也可以是硬碟
    具體可參考傳智部落格的《SSH》。
    其實我們上面說的Session找不到對應的物件就去資料庫中找是不太正確的,Session找不到會去二級快取SessionFactory找(如果配置了二級快取的話),參考《SSH》的P204-P206,有例子說明

相關文章