2010-06-23 69 views
1

我最近採用了我們項目的數據庫/休眠方面,並且在理解關於使用管理會話的設計基礎知識方面遇到了很多麻煩。我應該使用非靜態會話的靜態嗎?

我們有一個util類,它包含一個只初始化一次的靜態會話。會話的檢索由系統中的每個DAO通過一個靜態方法getBoundSession()來使用。該應用程序全天候運行。這是一個常見的設計?

其中一個非常有用的好處是可以在整個業務邏輯層中使用域對象上的懶惰屬性/集合,因爲會話始終處於打開狀態。另一個好處是,retreived對象將保持在會話中緩存。

我覺得我們必須以一種錯誤的方式使用Hibernate,看起來只有一次永久打開的會話似乎不正確。當單獨的線程正在使用util類時,它也會導致問題,從而共享會話。另一方面,我無法找到一種方法來實現上述優點(特別是第一種)採用不同的設計。任何人都可以對此有所瞭解嗎?

感謝

詹姆斯

回答

2

我們有一個util類,它包含一個只初始化一次的靜態會話。會話的檢索由系統中的每個DAO通過一個靜態方法getBoundSession()來使用。該應用程序全天候運行。這是一個常見的設計?

不是這樣。客戶端/服務器應用程序中的最常見模式是會話每請求和一個會話每個應用程序多用戶應用程序中的方法不僅是反模式,它是完全錯誤的:

  • A Session不是線程安全的。
  • 如果您希望保持對象狀態和數據庫同步,您應該在Hibernate異常之後回滾事務並返回關閉Session
  • 如果保持打開時間過長,Session將無限增長。

你真的需要閱讀整個Chapter 11. Transactions and Concurrency

另一方面,我無法找到一種方法來實現上述優點(特別是第一種)與不同的設計。

可以使用OSIV(Open Session In View)模式或明確載入每個流需要的內容。如果您想從全局緩存中受益,請使用二級緩存。

+0

非常感謝您的回覆。我一定會離開並閱讀第11章。如果你不介意的話,最後一個問題是:我們有一個7級的類層次結構(通常是一對多關係),我擔心顯式加載這個層次結構將是非常重要的昂貴而沒有延遲加載。這種緊密耦合的領域模型是否具有設計缺陷?我認爲這一定是我們靜態會話背後的推理。 – James 2010-06-23 16:22:55

+0

@James:如果你不使用OSIV模式,我不是故意要說「不要使用延遲加載」,而是要明確*提取所需的數據。不,我不認爲你的設計是有缺陷的。 – 2010-06-23 16:36:30

+0

假設我們有一個層次:'客戶'有許多'訂單'有許多'產品'有許多'材料' 由於我們已經使用了一個靜態會話,在總線邏輯中一個客戶被加載,通過從方法到方法延遲加載成員許多次 - 比如計算每個訂單的產品數量,以及訂單中最昂貴的材料。 如果會話已關閉,則延遲加載無用,因此業務邏輯無法導航對象圖。所以我只能想到業務層管理會話(這看起來很糟糕?),或者刪除客戶的深度並添加DAO,例如查找最昂貴的材料。 – James 2010-06-23 17:19:50

1

保持會話打開的時間過長是正常(雖然這不應該是永恆:-)會話應該確定工作的單位 - 一套連貫的邏輯上屬於一起的查詢/更新。您可以在您的應用中識別這些單位 - 例如客戶端請求或對話?如果是這樣,請爲其中的每個創建一個單獨的會話。

您還應該明確地爲每個線程使用一個單獨的會話(通常,一個工作單元由單個線程處理)。一個簡單的方法是使用thread local storage

0

這是一種反模式。

如果您爲所有請求使用一個會話。然後考慮幾乎同時運行的100個客戶端(100個請求/線程)。你從會話中分離出一些東西,但是另一個用戶重新加載了相同的東西。您將需要同步化,這將達到性能。而且你會完全隨機的行爲,這將是噩夢調試。

SessionFactory是靜態/每應用程序,而不是Session。工廠應該根據需要建立一個會話。在休眠時閱讀sessions and transactions文檔。

相關問題