Hibernate中的list和iterate,load和get

[b]1 List和Iterator[/b]
a. list--從數據庫中查詢出所有的對象列表;只能利用查詢緩存(但在交易系統中查詢緩存作用不大),無法利用二級緩存中的單個實體,但list查出的對象會寫入二級緩存,但它一般只生成較少的執行SQL語句,很多情況就是一條(無關聯)。
b. iterator--只從數據庫中查詢出所有的對象id;可以利用二級緩存,對於一條查詢語句,它會先從數據庫中找出所有符合條件的記錄的ID,再通過ID去緩存找,對於緩存中沒有的記錄,再構造語句從數據庫中查出,因此很容易知道,如果緩存中沒有任何符合條件的記錄,使用iterator會產生N+1條SQL語句(N爲符合條件的記錄數)
c. 例如:
List<Student> ls = session.createQuery("from Student".list();
Iterator it = ls.iterator();
//這種用法生成的SQL:
Hibernate: select student0_.id as id0_,
student0_.name as name0_,
student0_.sex as sex0_,
student0_.age as age0_,
student0_.birthday as birthday0_ from student student0_
一次性把所有學生查出來

Iterator it = session.createQuery("from Student".iterate();
這種用法會先把所有ID查出來 SQL語句:select student0_.id from student student0_
迭代的過程中 在用每個ID 去查處ID對應的記錄
SQL語句:
Hibernate: select student0_.id as id0_,
student0_.name as name0_,
student0_.sex as sex0_,
student0_.age as age0_,
student0_.birthday as birthday0_ from student student0_ where student0_.id = ?

[b]2 load和get[/b]
Hibernate中有兩個極爲相似的方法get()與load(),他們都可以通過指定的實體類與ID從數據庫中讀取數據,並返回對應的實例,但Hibernate不會搞兩個完全一樣的方法的,它們間的不同在於:
 1.如果找不到符合條件的紀錄,get()方法將返回null.而load()將會報出ObjectNotFoundEcception.
 2.load()方法可以返回實體的代理類實例,而get()永遠只返回實體類.
3.load()方法可以充分利用二級緩存和內部緩存的現有數據,而get()方法只在內部緩存中進行查找,如沒有發現對應數據將跳過二級緩存,直接調用SQL完成查找.

呵呵,沒有說到根本點上,hibernate中get方法和load方法的根本區別在於:如果你使用load方法,hibernate認爲該id對應的對象(數據庫記錄)在數據庫中是一定存在的,所以它可以放心的使用,它可以放心的使用代理來延遲加載該對象。在用到對象中的其他屬性數據時才查詢數據庫,但是萬一數據庫中不存在該記錄,那沒辦法,只能拋異常,所說的load方法拋異常是指在使用該對象的數據時,數據庫中不存在該數據時拋異常,而不是在創建這個對象時。由於session中的緩存對於hibernate來說是個相當廉價的資源,所以在load時會先查一下session緩存看看該id對應的對象是否存在,不存在則創建代理。所以如果你知道該id在數據庫中一定有對應記錄存在就可以使用load方法來實現延遲加載。
對於get方法,hibernate會確認一下該id對應的數據是否存在,首先在session緩存中查找,然後在二級緩存中查找,還沒有就查數據庫,數據庫中沒有就返回null。

對於第2點,雖然好多書中都這麼說:“get()永遠只返回實體類”,但實際上這是不正確的,get方法如果在session緩存中找到了該id對應的對象,如果剛好該對象前面是被代理過的,如被load方法使用過,或者被其他關聯對象延遲加載過,那麼返回的還是原先的代理對象,而不是實體類對象,如果該代理對象還沒有加載實體數據(就是id以外的其他屬性數據),那麼它會查詢二級緩存或者數據庫來加載數據,但是返回的還是代理對象,只不過已經加載了實體數據。

3。胡說八道,前面已經講了,get方法首先查詢session緩存,沒有的話查詢二級緩存,最後查詢數據庫;反而load方法創建時首先查詢session緩存,沒有就創建代理,實際使用數據時才查詢二級緩存和數據庫。

總之對於get和load的根本區別,一句話,hibernate對於load方法認爲該數據在數據庫中一定存在,可以放心的使用代理來延遲加載,如果在使用過程中發現了問題,只能拋異常;而對於get方法,hibernate一定要獲取到真實的數據,否則返回null。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章