2017-09-10 69 views
4

我的印象是session.load()加載緩存中的代理對象,而session.get()總是碰到數據庫,但在觀看JavaBrains video後我感到困惑。休眠:在session.load的情況下急切和延遲加載vs session.get

根據這段視頻,當我們調用下面的get方法時,它會在內存中加載代理對象UserDetails

user = (UserDetails) session.get(UserDetails.class, 1); 

UserDetails結構

enter image description here

雖然在註釋部分,一個傢伙說:

沒有代理用戶類,而不是代理對象 集合已創建。

現在有兩個問題在這裏。

1st:涉及session.load()和session.get()的取回策略和創建代理對象,這個問題已經由我回答。

第二種:在這種情況下,代理對象將爲UserDetails或收集創建(仍有待回答)。

感謝

回答

2

我得到了答案here

  1. Hibernate默認會創建運行時代理。它將對象加載爲代理,除非指定了獲取模式或設置爲false。 這就是爲什麼它總是創建一個對象的代理(如果我們使用get()或load()以及任何獲取策略)無關緊要。

  2. get()首先在緩存中檢查代理是否存在,如果不存在,它將觸發數據庫,​​同時在緩存中創建對象的代理並返回代理對象,一旦對象加載到緩存中,隨後的下一個調用將執行可重複讀取。

  3. load()總是檢索代理對象。它從永久上下文緩存中讀取數據,並且如果代理不存在於緩存中,它將返回null。

+0

是的,這正是我在評論中提到的。爲了測試您的情況,爲什麼不在代碼中嘗試'session.clear()'並分析結果? 清除二級緩存,請閱讀: https://dzone.com/articles/clearing-hibernate-second-leve –

+0

@Rahul,的確你是對的,如果你能回答第二個問題「在這個問題代理對象將創建UserDetails或收集?「 – Gaurav

1

這裏,UserDetails是家長和Address是孩子。 Hibernate實際上是懶加載兒童Address。 因此,最終所有的子元素(在這種情況下爲Address)在加載父元素(本例中爲UserDetails)時未預先加載。

所以,當你這樣做:

user = (UserDetails) session.get(UserDetails.class, 1); 

休眠沒有實際加載的所有子(Collection<Address>)。 而是僅當您明確地訪問它們時,Hibernate纔會加載Address。所以休眠不會打DB的Address表,除非你真的需要它們,這就是延遲加載的目的。

這意味着通過延遲加載是什麼,而你得到的UserDetails代理對象,它並不真正打Address表,除非您嘗試顯式訪問集合元素。換句話說,您需要遍歷集合進行休眠以獲取Address表。

您可能會陷入每次爲每個孩子敲擊數據庫(Address)的情況。因此,請撥打listOfAddresses.size()以便一次加載所有的孩子。

還要注意的是延遲加載將默認爲發生一到多許多一對多箱子。

+0

我的問題實際上是關於在session.load()和session.get()的情況下獲取策略和創建代理對象,而不僅僅是急切和懶惰的加載。 – Gaurav

+0

那麼你必須明白'Load()'實現**延遲加載**和'get()'永遠不會返回代理。 –

+0

@ Rahul,這就是爲什麼它加載代理對象的情況下get() – Gaurav

-1

2問題回答: 代理服務器的地址爲您的問題上下文,您可以這麼說。 深入或詳細地說,第一個hibernate也會爲userdetail創建代理,但只要查詢命中,代理將有數據。但是,由於默認情況下hibernate是延遲加載,而Address是UserDetail中的子代,它將僅作爲代理返回,並且您將只獲得Address(主鍵值)的id值。 不要對代理服務器感到困惑。代理將爲所有類的父類(UserDetail)或子類(Address)創建,但對於子類,它將只有id數據。

+0

我只想知道誰投下了這個票。你可以解釋這裏有什麼問題。 –