2014-01-24 133 views
4

在Spring MVC應用程序中處理延遲加載對象的最佳解決方案是什麼?我已經對此主題進行了一些搜索,並找到以下解決方案:延遲加載處理(Hibernate + Spring MVC)

打開會話:爲每個請求打開一個會話並在視圖呈現後關閉它。這個解決方案的問題是我需要延遲加載Spring MVC模型之外的對象(例如Junit測試用例)。關於此解決方案的另一個討論問題是異常處理如果事務在視圖呈現期間拋出異常怎麼辦?

明確打開會話:只要我需要延遲加載對象,就會明確地打開一個會話。其實這個解決方案應該可以工作,但我不認爲這是正確的方法。

使用AOP:創建一個在會話中包裝延遲加載方法的方面。這可能是一個解決方案,但我不知道我應該定義什麼級別的應用程序

創建自定義查詢:爲延遲加載創建查詢併爲急切加載查詢。這種解決方案實際上工作,但在我看來,延遲加載模式的錯誤應用

+0

檢查OSIV優點/缺點這篇文章http://blog.jhades.org/open-session-in-view-pattern-pros-and-cons/ –

+0

使用自定義查詢的問題是,他們強制加入到相關對象上,這並不總是最佳的解決方案。有時候,對於主對象有1個查詢並且對於相關對象有N個單獨的查詢更有效。 – Solubris

+0

此外,其漂亮到查詢從遲緩裝載中分離的,因爲它意味着可以具有用於延遲加載一個方法(例如:loadRelationsRequiredByDefault()),這可以通過許多不同的查詢返回相同的對象被重新使用(或列表對象)。 – Solubris

回答

2

有沒有解決辦法,就是始終在所有情況下更好,問題是@Transactional服務層上不會保持會話開放渲染階段開始時。

在渲染開始之前會話被刷新,事務提交併且會話關閉。要解決這個

一種方法是使用加載需要在取決於正在興建視圖中的每個時刻數據的自定義查詢。

另一種方法是使用在視圖中打開的會話,這使渲染時宣佈會議開幕,但它可能是由於誤用延遲加載導致在應用N + 1點的問題。

同樣在視圖中打開會話可能會導致無法重複讀取的問題,其中一些數據被服務層讀取並用於提交事務,但是當視圖呈現開始時數據不再可用或被修改時,以及這對構建視圖非常重要。 (是我開發的許多與Hibernate相同的開發人員)。

不同的方法有不同的優缺點,具體取決於項目的優先順序。如果不需要編寫自定義查詢的便利性有很大的寫作意義,那麼OSIV是一個不錯的選擇。偶爾出現的N + 1問題可以逐案解決,並與之共存。

如果強調的是保持在控制之下的查詢,因爲該應用程序,例如性能的關鍵,然後自定義查詢是一種選擇。

實在是沒有明確的最佳解決方案。如果您使用在客戶端(類似於angular.js)運行的視圖技術而不是服務器,那麼您不會遇到這類問題,因爲不涉及服務器端渲染。

0

我不舒服,如果它符合您的要求,而不是如果它是「正確的方式來處理它,但我利用@事務註釋。所以我會:

@Autowired 
AccountDAO accountDAO; 

@Transactional 
public List<String> getNamesOfAccount(String accountName){ 
    Account account = accountDAO.get(accountName); 
    return account.getNames(); 
} 

帳戶中的名稱屬性是懶惰的,並在返回之前加載。 如果有更好的方法讓我們聽到!

+0

這可能是一個解決方案。我不知道這是否是最好的方法。我會等待別人的建議。 – JJJ

+0

該解決方案的好處在於,您的DAO中只有EntityManager/SessionFactory。如果您不調用getNames(),則不會加載任何內容。如果你這樣做,那麼Spring會爲你做所有事情,而且你不必打開會話或其他事情。 –

+0

沒有說服我的是,我不能通過域對象接口訪問「懶域」,但只能通過DAO訪問。 – JJJ