2009-12-23 64 views
1

我正在處理的應用程序使用session.load()通過標識符來執行所有查詢。鑑於它無法找到標識符並引發異常時導致的混亂,我正在考慮將它交換到session.get()。但在我這樣做之前,這是系統的一個基本部分,我想確保兩種方法之間絕對沒有其他區別。是否有任何理由可以想到爲什麼原始開發者會選擇load()而不是處理無效ID()?在Hibernate中,session.get()和session.load()之間有什麼區別,除了如何處理不好的ID?

編輯:如上所述,我完全知道get返回false並且加載拋出異常。我問是否有任何其他方式,他們不同。

+2

他們,複製 - http://stackoverflow.com/questions/608947/hibernate-difference-between-session-get-and-session-load – Bozho 2009-12-23 18:04:00

回答

2

是不是因爲Get永遠不會返回代理而Load呢?

http://ayende.com/Blog/archive/2009/04/30/nhibernate-ndash-the-difference-between-get-load-and-querying-by.aspx

我認爲這是很重要的:

這是爲什麼有用嗎?那麼,如果你知道 那個值存在於數據庫中,那麼你不想支付額外的 選擇那個,但是你想要 得到那個值,所以我們可以把 引用加到一個對象上,您可以使用 負載這樣做: 上面的代碼不會導致 選擇到數據庫,但是當我們 提交事務,我們將設置 CustomerID列1。這是 NHibernate的如何保持OO外觀 當給你相同的優化 好處直接與 低級API工作。

從NH 2。0參考文獻:如果沒有 匹配的數據庫記錄

注意,load()方法將拋出一個 不可恢復的異常。如果使用代理映射的類爲 ,則Load()會返回一個 對象,該對象是未初始化的代理 ,直到調用 對象的方法時纔會實際觸及數據庫 。如果您希望創建關聯 而不實際從數據庫加載 ,則此行爲非常有用 。

如果你不確定是否有匹配 行存在,應該使用get() 方法,它訪問數據庫 立即如果 沒有匹配的行,返回null。

+1

至少在Java Hibernate中,如果在會話中已經爲該實體創建了代理,則.get()*可以*返回代理。這樣你最終不會得到通過一個路由的代理引用和通過另一個非代理引用(打破'你可以使用==來測試映射到同一行的對象'功能) – araqnid 2009-12-23 16:22:42

0

像往常一樣,這個最好的參考是documentation

Session.get()

返回與給定的識別符,或空給定實體類的持久例如,如果不存在這樣的持久實例。 (如果實例,或者實例的代理,已經與會話相關聯,返回實例或代理。)

Session.load()

返回給定的實體類的持久化實例與給定的標識符,假設實例存在。

您不應該使用此方法來確定實例是否存在(請改爲使用get())。只用它來檢索你認爲存在的實例,其中不存在將是一個實際的錯誤。

所以,區別在於處理不存在的實例的方式。

+0

權,但我詢問是否有任何*其他*區別。我很久以前就開始閱讀開發人員的想法,對我來說,他們會使用負載是沒有意義的。所以,我想要考慮他們可能有的任何其他原因。 – abeger 2009-12-23 15:44:41

0

一個好的方法如下所示

如果需要調用一個getter方法,然後使用get方法。 get方法命中數據庫。

public class AccountServiceImpl implements AccountService { 

    private SessionFactory sessionFactory; 

    public BigDecimal getBalance(Integer acountId) { 
     // You need to know your balance 
     // So you need to use get method to access the database 
     Account account = (Account) sessionFactory.getCurrentSession().get(Account.class, accountId); 

     return account.getBalance(); 
    } 

} 

如果需要調用getter和setter方法,使用get方法。

針對ChssPly的評論:

JPA與Hibernate書上說,有關負載方法

的load()方法總是試圖返回一個代理,只返回如果初始化的對象實例它已經由當前的持久性上下文管理。

而且

它擊中的數據庫,只要你嘗試訪問返回的佔位符,並迫使其初始化

因此,他是對的,當你建立一個單一的屬性。

但在JPA與Hibernate本書中的以下情形

這是常見的,以獲得持久化實例將其指定爲另一個實例的引用。例如,假設您只需要該項目僅用於一個目的:使用註釋設置關聯:aComment.setForAuction(item)。

如果這是你打算處理的項目,代理服務器將會正常工作;沒有必要去打數據庫 。換句話說,保存註釋時,您需要插入到COMMENT表中的項目的外鍵值。

一個Item的代理只提供:一個標識符值包裝在一個佔位符中,看起來像真實的東西。

問候,

+0

你的第一個例子是沒有說明'load()'的一個很好的用法。當您調用setPassword()方法時,您的User實例將被物理加載。更合適的方案將涉及在@ManyToOne關係上加載/設置另一個實體。 – ChssPly76 2009-12-23 17:28:41

+0

謝謝,我已經看到你說的和你說得對。但是我不明白爲什麼Hibernate需要在你設置一個屬性時選擇,因爲JDBC是用來執行數據庫操作的底層機制,它返回更新的行數。因此,我認爲這不是必要的。 – 2009-12-23 19:15:49

+0

由於可能的副作用。 Hibernate無法知道'setUser()'方法的真正用處 - 你可能有一些直接訪問實體狀態的邏輯。另外,還有各種各樣的回調,Hibernate在契約上有義務在保存時觸發(例如'findDirty()'),這可能也是這樣做的。因此,在非id屬性訪問時立即填充實體狀態。 – ChssPly76 2009-12-23 20:16:51

相關問題