Hibernate檢索優化
對物件進行檢索的目的是為了將物件載入到記憶體,讓程式使用其資料。所以,物件檢索也稱為物件載入。直接通過 get()、load()等查詢語句載入的物件,稱為主載入物件,而主載入物件所關聯的物件,稱為關聯載入物件,或從載入物件。根據檢索物件的不同,可以將檢索優化分為兩類:
(1)當前物件檢索優化
(2)關聯物件檢索優化
對於不使用優化進行物件檢索的過程,稱為直接載入;否則稱為延遲載入,或懶載入。
1、當前物件檢索優化
對於當前物件進行檢索,即對主載入物件進行檢索。通常使用 Session 提供的兩個方法:get()與 load()。預設情況下,get()為直接載入,而 load()為延遲載入。
get()方法的直接載入指,當代碼中出現 get()時,後臺馬上會呼叫執行 select 語句,將物件直接載入到記憶體。
load()方法的延遲載入指,當代碼中出現 load()時,後臺並不會馬上呼叫執行 select。只有當代碼中真正要訪問除了物件的主鍵 id 屬性以外的其它屬性時,即真正要訪問物件的詳情時,才會真正執行 select 語句,即此時才會將物件真正載入到記憶體。
為什麼對id屬性的訪問不會引發select的執行?
因為對於 load()方法,第二個引數必須為要載入物件的 id,此值不用從 DB 中獲取,直接從 load()引數即可獲得。所以,對 id 屬性的訪問,不會引發 select 的執行。
當執行完load()後,系統都做了些什麼?
當執行完load()後,系統會生成物件的代理物件,該代理物件進行了位元組碼增強。從該代理物件的屬性 handler 的值可以看出兩點:
Javaassist 名稱部分,說明其進行了位元組碼增強。在 Hibernate 的 Jar 包中,required 目錄下的 javassist-3.18.1-GA.jar 是 Java 位元組碼操作助手,可完成位元組碼增強。
LazyInitializer 名稱部分,說明其採用了延遲載入技術。
當執行完load()後,handler屬性的initialized屬性值為false,說明該代理物件尚未被初始化。
當執行完對id的輸出後,會立即輸出id的值,此時,還未執行select。
當執行對物件其他屬性輸出時,就需要從DB中查詢了。此時才會真正呼叫執行select,然後輸出name的值。此時,再檢視handler的initialized屬性值,已由false變為了true。
get()與load()的另一個區別:當要檢索的物件在DB中不存在時,get()方法返回值為null,而load()會丟擲異常。
2、關聯物件檢索優化
對於關聯物件的檢索,也可進行延遲載入優化。,要依據對映檔案的配置。對映檔案中對於關聯物件檢索的優化配置屬性有兩個:lazy、fetch。這兩個屬性是對關聯物件的檢索進行優化,所以它們是設定在對映檔案的關聯屬性對映中的。
lazy 與 fetch 各具有若干值,它們不同值的組合,表示不同的物件載入策略。根據這兩個屬性配置位置的不同,分為兩種:
(1)多端載入優化
(2)單端載入優化
多端載入優化:所謂多端關聯載入優化,是指一方為主載入物件,而多方作為從載入物件,對於多方載入時所進行的延遲載入優化配置。鑑於此,fetch、lazy 應設定在一方對映檔案的關聯屬性中,即設定在集合<set/>標籤之中。
lazy 用於指定物件載入時機,即何時載入問題。此時其取值有:false、true、extra。
fetch 用於指定物件載入方式,即如何載入問題,即採用哪種 select 查詢,此時其取值有:join、select、subselect。
lazy取值 | 意義 |
lazy=“false” | 直接載入 |
lazy=“true” | 延遲載入 |
lazy=“extra” | 特別延遲載入。執行聚合函式可以解決的,不進行詳情查詢 |
fetch取值 | 意義 |
fetch=“join” | 採用迫切左外連線查詢 |
fetch=“select” | 採用普通select查詢 |
fetch=“subselect” | 採用子查詢(Hibernate5 不支援該策略) |
單端載入優化:所謂單端載入優化,是指多方為主載入物件,而一方作為從載入物件,對於一方載入時所進行的延遲載入優化配置。鑑於此 fetch、lazy 設定在多方對映檔案的關聯屬性中,即<many-to-one/>標籤中。
lazy 用於指定物件載入時機,即何時載入問題。此時其取值有:false、proxy、no-proxy。
fetch 用於指定物件載入方式,即如何載入問題,即採用哪種 select 查詢,此時其取值有:join、select。
lazy取值 | 意義 |
lazy=“false” | 直接載入 |
lazy=“proxy” | 使用位元組碼代理。關聯屬性是否延遲載入,由該類的lazy值決定 |
lazy=“no-proxy” | 不研究 |
fetch取值 | 意義 |
fetch=“join” | 採用迫切左外連線查詢 |
fetch=“select” | 採用普通select查詢 |