hibernate中的n 1問題

2021-08-01 11:29:47 字數 2150 閱讀 4305

前提:hibernate預設表與表的關聯方法是fetch="select",不是fetch="join",這都是為了懶載入而準備的。   

1)一對多() ,在1的這方,通過1條sql查詢得到了1個物件,由於關聯的存在 ,那麼又需要將這個物件關聯的集合取出,所以合集數量是n還要發出n條sql,於是本來的1條sql查詢變成了1 +n條 。   

2)多對一,在多的這方,通過1條sql查詢得到了n個物件,由於關聯的存在,也會將這n個物件對應的1 方的物件取出, 於是本來的1條sql查詢變成了1 +n條 。   

3)iterator 查詢時,一定先去快取中找(1條sql查集合,只查出id),在沒命中時,會再按id到庫中逐一查詢, 產生1+n條sql   

1 )lazy=true, hibernate3開始已經預設是lazy=true了;lazy=true時不會立刻查詢關聯物件,只有當需要關聯物件(訪問其屬性,非id欄位)時才會發生查詢動作。    

2)使用二級快取, 二級快取的應用將不怕1+n 問題,因為即使第一次查詢很慢(未命中),以後查詢直接快取命中也是很快的。剛好又利用了1+n 。    

3) 當然你也可以設定fetch="join",一次關聯表全查出來,但失去了懶載入的特性。   

a. list--從資料庫中查詢出所有的物件列表;只能利用查詢快取(但在交易系統中查詢快取作用不大),無法利用二級快取中的單個實體,但list查出的物件會寫入二級快取,但它一般只生成較少的執行sql語句,很多情況就是一條(無關聯)。  

b. iterator--只從資料庫中查詢出所有的物件id;可以利用二級快取,對於一條查詢語句,它會先從資料庫中找出所有符合條件的記錄的id,再通過id去快取找,對於快取中沒有的記錄,再構造語句從資料庫中查出,因此很容易知道,如果快取中沒有任何符合條件的記錄,使用iterator會產生n+1條sql語句(n為符合條件的記錄數)  

hibernate中有兩個極為相似的方法get()與load(),他們都可以通過指定的實體類與id從資料庫中讀取資料,並返回對應的例項,但hibernate不會搞兩個完全一樣的方法的,它們間的不同在於:  

如果找不到符合條件的紀錄,get()方法將返回null.而load()將會報出objectnotfoundecception.

load()方法可以返回實體的**類例項,而get()永遠只返回實體類.  

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。

Hibernate解決n 1問題

觀點 對於n 1問題的理解。一般而言說n 1意思是,無論在一對多還是多對一當查詢出n條資料之後,每條資料會關聯的查詢1次他的關聯物件,這就叫做n 1。但是我的理解是,本來所有資訊可以一次性查詢出來,也就是簡單的連表查詢,但是hibernate會首先查詢1次得到當前物件,然後當前物件裡面的n個關聯物件...

HIBERNATE的N 1查詢問題

在session的快取中存放的是相互關聯的物件圖。預設情況下,當hibernate從資料庫中載入customer物件時,會同時載入所有關聯的order物件。以customer和order類為例,假定orders表的customer id外來鍵允許為null,圖1列出了customers表和order...

hibernate的n 1查詢問題

在 session 的快取中存放的是相互關聯的物件圖。預設情況下,當 hibernate 從資料庫中載入 customer 物件時,會同時載入所有關聯的 order 物件。以 customer 和order 類為例,假定 orders 表的customer id 外來鍵允許為 null,圖1 列出了...