1. 程式人生 > >hibernate檢索小結之——查詢優化和延遲載入

hibernate檢索小結之——查詢優化和延遲載入

Hibernate抓取(檢索方式)

檢索分為:立即檢索和延遲檢索

區別和原理:立即檢索當(使用者)請求一發立刻向資料庫傳送sql語句,不管該物件有沒有被使用(訪問去屬性)。而延遲檢索則是類似於保留查詢,只有在該物件唄使用的時候才會想資料庫傳送sql語句,其實延遲檢索返回的是目標類的代理子物件,沒有向資料庫傳送任何請求,所有沒有初始化,在斷點模式下可以看見雖然該物件存在(有記憶體地址,不為null),但發現該你物件沒有被初始化,只有當訪問該物件的時候才會被初始化。當然還可以使用hibernate具類的initialize方法強制初始化代理物件,當訪問物件的延遲載入時,底層也是呼叫Hibernate

工具類的initialize方法

小結論:延遲載入提高效率(避免一些不必要的sql查詢),而立即載入資料齊全(後續的查詢可以直接到快取裡面查詢)

抓取的策略:一方對多方,主表和重表的策略(主表查詢的時候從表是否聯動),多方對一方,重表和主表的策略(查詢重表的時候是否聯動主表),注意:這裡的聯動指的是向資料庫立刻傳送sql語句。

配置的含義:fetch表示立即載入,lazy表示延遲載入(懶載入)Fetch的值有兩中,joinselectfetch的值為join的時候表示關聯(以當前為主表左連結)查詢,fetch的值為select的時候,非關聯查詢(只查詢自己,不去查詢關聯的表),lazy的值有四種,

tureflase,extra以及proxy(一些基本沒意義的值就不提了).lazy的值為true表示延遲載入,false表示不延遲(立即載入).extra加強延遲載入(及其懶惰載入)proxy這個不確定要看依賴,當然這些只是相對的,具體還還看相互的搭配以及查詢的方式。

小總結:fetchsql語句的生成方式(單表查詢還是連結串列查詢)lazy是資料初始化的時間(立即初始化還是訪問其id外的屬性的時候初始化),所以當fetchajoin的時候忽略lazy的值(因為連結串列查詢肯定把關聯資料查詢出來了),當joinselect的時候(單表查詢),此時lazy的值決定是否立即對關聯資料進行檢索。

配置與載入:一方(主表)預設的配置 fetch=join” lazy=true(連結串列查詢和延遲載入。此時的延遲會被忽略)。所以如果查詢當前物件的時候(預設配置),會立即和重表(多方)進行左連結查詢,吧與之相關的資料全部查詢出來。多方(重表)預設配置是fetch=”select” lazy=”proxy”(單表查詢,延遲載入,但不確定),這個要看關聯方的類載入(class 上配置的lazy 的屬性)。當查詢當前物件的時候不會立即載入所有的資料,因為是簡單查詢(單表),所以不會把與之關聯的主表的資料查詢出來,僅僅只顯示當前資料。所有不做任何的配置(多方和一方都是預設配置), 查詢一方的時候會預設吧多方資料關聯出來,而查詢多方則不會關聯一方的資料。 如果(一方)採用預設配置,當查詢一方(主表)的時候會連帶吧多方(重表)的資料全部查詢出來,而且資料資訊大量重複,很多臃餘的資料。而且有時候根本用不到重表(多方)的資料,這樣影響了載入效率,並佔用了記憶體,如果(多方)採用預設配置,查詢當前物件的時候不會連帶查詢出主表的資料,僅僅只載入自己當前的資料,

小分析:都用預設配置(主表關聯查詢,立即載入(此時lazy被忽略),重表簡單查詢,延遲載入)。如果查詢主表會有臃餘的資料和佔用記憶體,這樣不好。而查詢重表資料不齊全,而且還要頻繁的向資料傳送sql語句,這樣也不好,所以預設配置查詢主表和重表都不好

小推薦:主表配置,單表查詢,延遲載入(fetch=select” lazy=true),從表配置:連結串列查詢,立即載入(fetch=join” lazy=false),個人認為主表用單邊查詢和延遲載入,重表採用連結串列查詢和立即載入。因為主表連帶出的資料比較多(一方連帶多方),所以單表比較好,說不定,資料根本用不到,而且再次查詢的時候資料不會臃餘,重表連帶出的資料比較少(多方連帶一方),每次查詢值會連帶一條資料,所以採用連結串列查詢和立即載入,此時主表和重表都有資料,要用主表的資料時不必再向資料庫傳送請求。

查詢與載入:凡事都有例外,以上的說法僅僅是針對get方式的查詢(通過id查詢),如果採用自定義查詢語句,hql語句和sql語句,則fetch的值將會被忽略,是否延遲載入完全有lazy來決定,這個就比較簡單了,如果是createQuery he createeSQLQuery方式的查詢,lazy的值為ture,表示延遲載入,flase表示立即載入,extra加強延遲載入

順帶提一下,extra加強延遲載入的含義,意思是隻有當訪問其裡面的po物件的id(主鍵)除外的屬性才會被載入,例如:通過使用者使用者連帶查詢出來該使用者的所有訂單,當訪問該訂單的個數的時候都不載入該訂單的資料,只有訪問具體的某個訂單的id除外的屬性的時候(比如訂單的金額)才會載入資料(載入該使用者的所有訂單不是載入一條訂單),而一般的延遲載入則在訪問其訂單數量的時候載入該使用者的所有訂單,同樣的如果返回一個list,如果訪問list裡面(po)物件的個數的事時候,不會載入,只有訪問list裡面的物件的屬性(非主鍵屬性)的時候才會被載入