hibernate 的中的session依照load()和get()按照引數的制定oid(objctid)去載入乙個持久化物件。另外query.list()方法則按照hql語句去載入持久化的物件。
以上的幾個方式都可以實現hibernate的持久化物件的載入。如果有不懂hibernate物件的"臨時狀態"、"游離態"、"持久態"、"刪除狀態"的小夥伴,自己先去了解下。
對於hibernate的以上的幾種檢索策略,我們先來了解下他們幾種的工作細節。
首先是session的load()方法,我們以customer和orders的例子來簡單說明下。customers與orders的關係是一對多的關係。我們這邊假定已經配置了這兩個物件hbm.xml的一對多單向關聯關係。
一、session的load(customers.class,new long(1))的方式返回的是乙個customer持久化物件的引用。這時候customer還沒有初始化。因此時不會出現sql查詢語句的執行。要等到真正使用到customer的時候才會進行初始化。也就是執行查詢語句。這時候如果在custmoers 中配置了
12 name="orders"
3 insever="ture"
4 lazy="true"
5 fetch= "select"
6 class=....>
7 >
lazyd的預設屬性是true,也就是說採用懶載入。
1、如果lazy設定為false的話,則會在初始化customers物件的時候就會去將customers所有orders物件進行查詢,這也叫立即檢索。這裡有個地方得值得注意的是,如果上面的set標籤中配置了fecth屬性為join,這時候load在真正執行查詢的時候,關聯物件的時候使用的的是迫切左外連線查詢,這樣的話,就算是顯式的設定lazy的屬性,也無意義。至於為什麼,我想熟悉sql查詢的都知道原因了。當然fecth屬性還有其他的一些選項例如select,subselect,fetch預設為select。
2、如果採用懶載入,也就是lazy設定為true的話,則在初始化customers只會對customers物件進行查詢操作。而在真正使用orders屬性時才對customers關聯的orders物件進行查詢操作。這裡得說明下:例如 在對order order = customer.iterator().next()迭代的時返回是orders的**例項。這時的order還沒有進行例項化,所以沒有進行sql查詢。只有在對其屬性或方法呼叫的時候,例如獲取訂單號:order.getorderno()的時候才對其進行例項化。
lazy還有其他選項 extra增強 ,例如獲取乙個訂單集合的size/contains等方法時,這時不會去初始化該orders,而是會向資料庫傳送一條sql去查詢獲取值,只有真正要用到集合元素值時才去例項化查詢資料庫。這種比較聰明的方式與lazy設定為true的區別就是在選擇懶載入的時機上extra更加「懶惰」,更加延遲。
二、session.get(customers.class,new long(1))。get採用的是立即檢索的策略,這裡customers一定會立馬初始化。
1、 如果在對orders的配置中,set中設定了lazy為true的話,則與load類似。等到真正使用orders的屬性的時候才會去做sql關聯查詢。
2、 如果 lazy設定為false,則在get()方法執行的時候也會立馬初始化orders的所有關聯物件。這種方式與上面load的第一種方式唯一的區別在與,load初始化比get的初始化customers的時機更晚,更延遲。
這裡注意的是,如果如果上面的set標籤中配置了fecth屬性為join,關聯物件的時候使用的的是迫切左外連線查詢。不管lazy是否設定為true,採用的也是立即載入。
三、query介面中的list()方法。 seesion.createquery(sql).list(),執行該方法後,程式會裡面向資料庫傳送sql去執行查詢操作。
1、 如果在對orders的配置中,set中設定了lazy為true的話,等到真正使用orders的屬性的時候才會去做sql關聯查詢。
2、 如果 lazy設定為false的話,則會立馬初始化orders的所有關聯物件。這個類似於get()方式。
這裡有個地方需要注意下,在query.list()的時候,它會fetch的join策略的,所以就算是顯式的設定了fetch為join,也不會採用迫切左外聯接查詢。
總結下load,get,query.list三種方式的區別:
1.load在對類級別的物件載入是有「延遲」作用的,而get和query.list採用的是立即檢索的策略。
2.在關聯一對多關聯關係的載入時,load與get和query.list 採用的都是同樣的策略,前提是在many一方的懶載入方式也是一致。
3.在get和load方式載入時,對fetch的策略是一致的。 而query.list是對fetch的join的策略是忽略的。
對於一對多的單向關聯關係的懶載入策略做了大致的分析。其實雙向也很好理解。
假設在orders.hbm.xml檔案中的中配置了以下配置:
12 insever="true"
3 lazy = "proxy"
4 ....
5class="..."
6/>
這裡前提是在customers.hbm.xml檔案中的set的inserver設定為false或者不顯式設定。預設為false。
1、這時在對orders物件進行載入的時候,如果customer採用的lazy是proxy方式,則採用**懶載入方式。也就說,只有當orders獲取它的custormer屬性的時候,才去載入與之關聯的customer物件。如果order的lazy採用的也是懶載入方式的話,則在獲取customer時不會獲取orders物件。
舉個例子:在get(orders.class,new long(1))的方法獲取orders的時候,會立馬載入orders物件,當獲取orders.getcustomer().getname()的時候,才會去載入customer物件,而如果再去獲取該customer物件下的orders的時候,才去載入orders。也就是說會去執行3次的sql,而每次執行一條sql語句。
而如果orders採用lazy為false的話,則與上面不用。則會在立馬載入orders,而後會在載入customers的同時一起載入orders物件。也就說這裡也會執行3條sql,但是分為2次執行,第一次一條查詢orders,第二次兩條,執行查詢customer和orders的查詢。
2、如果customer採用的lazy是no-proxy方式,則證明採用非**懶載入,這個與上面的區別在於這種方式是,在對orders載入完後,只有一旦獲取customer屬性時返回的就是customers的例項,而不是**例項。這樣就會立馬對customers進行例項化。其他的與proxy的一致。也就是說區別在於對customers物件的延遲載入時機的策略不同。
3、lazy的選項還可以是false,也就說。在對orders進行載入的時候,會立馬對customers進行立刻檢索。也就說會裡面發出3條sql語句。2次查詢order,一次查詢customer。
關於hibernate的懶載入,這裡講的只涉及到了一對多的關聯關係**不多,但懂的人應該可以理解。還有一對多,一對一,多對多。。hibernate都有自己的策略,而且都很靈活。後續會給大家補上。
Hibernate 檢索策略
在預設情況下,當hibernate從資料庫中載入物件時,會同時載入所有關聯的物件.但實際應用中可能不需要使用其關聯的物件,這樣就可能通過設定hibernate的檢索策略,來優化檢索效能.hiberante提供了3種檢索策略 1 立即檢索 2 延遲檢索 3 迫切左外連線檢索 下面先從概念上去理解,先在...
Hibernate檢索策略
預設的檢索策略是立即檢索。在hibernate對映檔案中,通過在上配置 lazy屬性來確定檢索策略。對於session的檢索方式,類級別檢索策略僅適用於load方法 也就說,對於get qurey檢索,持久化物件都會被立即載入而不管lazy是false還是true.一般來說,我們檢索物件就是要訪問它...
hibernate 檢索策略
本文主要是學習hibernate的檢索策略 1 類級別的檢索策略有兩種一種是立即檢索,一種是延遲檢索,僅影響load操作 立即檢索,是類的預設檢索方式,或者設定了lazy false 也是立即檢索方式,即執行load操作之後會立馬返回相應的資料。延遲檢索,當類設定lazy true 時,hibern...