2009-03-04 68 views

回答

111

Hibernate forum

這從本書在Hibernate的行動。好一個閱讀本..


由標識符 檢索對象下面的休眠代碼片段從數據庫檢索用戶對象:

User user = (User) session.get(User.class, userID); 

的get()方法是特殊的,因爲該標識符唯一標識一個類的單個實例。因此,應用程序通常使用該標識符作爲持久對象的方便句柄。通過標識符檢索可以在檢索對象時使用高速緩存 ,如果對象已被高速緩存,則避免數據庫命中。 Hibernate也提供了一個負載()方法:

User user = (User) session.load(User.class, userID); 

負載()方法是老年人;由於用戶 請求,get()被添加到Hibernate的API中。差異是微不足道的:

如果load()無法在緩存或數據庫中找到該對象,則拋出異常 。 load()方法永遠不會返回null。如果找不到對象,則get()方法返回 。

load()方法可能會返回代理而不是實際的持久實例。 代理是一個佔位符,它在第一次訪問 時觸發加載實際對象;另一方面,在( ),get()永遠不會返回代理。 get()和load()之間的選擇很簡單:如果您確定存在持久對象 ,並且不存在將被視爲例外,則load()是一個不錯的選項。如果您不確定是否存在具有給定 標識符的持久實例,請使用get()並測試返回值以查看它是否爲null。使用load()具有進一步的含義:應用程序可以檢索到持久實例的有效引用(代理),而不觸及數據庫以檢索其持久狀態。因此, load()在緩存或數據庫中未找到持久對象 時可能不會引發異常;當代理服務器 被訪問時,將會拋出異常。 當然,通過標識符檢索對象並不像使用任意的 查詢那麼靈活。

+1

我正在調試一個問題,其中session.Get ()正在返回代理! – 2010-03-29 15:03:03

+7

非常感謝!對我來說,錢的一部分是:「如果load()無法在緩存或數據庫中找到對象,則拋出異常。如果找不到對象,則get()方法返回null。」 – Chris 2010-07-28 04:23:20

14

那麼,至少在nhibernate中,session.Get(id)將從數據庫中加載對象,而session.Load(id)只會在不離開服務器的情況下爲其創建代理對象。與您的POCO(或POJO :)中的所有其他惰性加載屬性一樣。然後,您可以使用此代理作爲對象本身的參考來創建關係等。

想象它有一個只保留Id的對象,如果你需要的話可以加載其餘的對象。如果你只是通過它來創建關係(如FK),這個ID就是你所需要的。

9

session.load()將始終返回一個「代理」(Hibernate術語)而不會觸及數據庫。在Hibernate中,proxy是一個具有給定標識符值的對象,其屬性尚未初始化,它看起來像是一個臨時假對象。 如果未找到任何行,則會引發ObjectNotFoundException。

session.get()總是命中數據庫並返回實際對象,這是一個表示數據庫行的對象,而不是代理。 如果未找到任何行,則返回null。

這些方法的性能也使差異。在兩個...

0

另外,我們必須小心,而使用負載,因爲它會拋出一個異常,如果對象不存在。只有當我們確定物體存在時,我們才必須使用它。

1

使用「load」而不是「get」的一個間接結果是,使用版本屬性進行樂觀鎖定可能無法像您期望的那樣工作。如果加載只是創建代理並且不從數據庫讀取,則不會加載版本屬性。該版本只會在/之後加載,如果以後引用該對象上的屬性,則會觸發選擇。與此同時,另一個會話可以更新該對象,並且會話將不具有執行樂觀鎖定檢查所需的原始版本 - 所以會話的更新將覆蓋另一個會話的更新而不會發出警告。

下面試圖勾畫出這個場景,其中兩個會話使用一個具有相同標識符的對象。在數據庫對象最初的版本是10

Session 1     Session 2 
---------     --------- 
Load object 
Wait a while.. 
          Load object 
          Modify object property 
          [triggers db 'select' - 
          version read as 10] 
          Commit 
          [triggers db update, 
          version modified to 11] 
Modify object property 
    [triggers db 'select' - 
    version read as 11] 
Commit 
    [triggers db update, 
    version modified to 12] 

實際上,我們希望會議1的提交失敗,樂觀鎖定異常,但它會在這裏取得成功。

使用「get」而不是「load」可以解決問題,因爲get會立即發出select,並且版本號會在樂觀鎖定檢查的正確時間加載。

2

還有一個額外的點::如果對象不在緩存以及對數據庫中找到Hibernate的Session類的

get方法返回null。 while load()方法拋出ObjectNotFoundException,如果在緩存以及數據庫上找不到對象,但永遠不會返回null。
它總是會返回一個「代理」(休眠期)而無需訪問數據庫:

0

一個很好的說明從http://www.mkyong.com/hibernate/different-between-session-get-and-session-load
session.load()找到。
在Hibernate中,proxy是一個具有給定標識符值的對象,其屬性尚未初始化,它只是看起來像一個臨時假對象。
它將始終返回具有給定標識值的代理對象,即使標識值不存在於數據庫中。但是,當您嘗試通過從數據庫中檢索其屬性來初始化代理時,它將使用select語句來訪問數據庫。如果找不到任何行,則會拋出ObjectNotFoundException。
session.get():
它總是碰到數據庫(如果沒有在緩存中找到)並返回真實對象,一個代表數據庫行的對象,而不是代理。
如果未找到任何行,則返回null。

0

load()無法從緩存或數據庫中找到該對象,拋出異常並且load()方法永遠不會返回null。

如果找不到對象,則get()方法返回null。 load()方法可能會返回代理而不是實際的持久實例get()永遠不會返回代理。

相關問題