2010-05-29 81 views
3

我處理的大,相當繁瑣的代碼庫遺留的Java應用程序。還有那個被存儲在請求之間HttpSession中一個相當標準的「用戶」的對象,所以servlet的頂部做的東西是這樣的:Hibernate的實體屬性值

HttpSession session = request.getSession(true); 
User user = (User)session.getAttribute("User"); 

老用戶認證層(這我就不一一介紹了,足以比如說,它沒有使用數據庫)正在被替換爲使用Hibernate映射到數據庫的代碼。所以'用戶'現在是一個Hibernate實體。

我對Hibernate對象生命週期的理解有點模糊,但好像將'User'存儲在HttpSession中現在成了一個問題,因爲它會在下一次請求期間在不同的事務中檢索。在這裏做什麼是正確的?我可以在下次使用Hibernate Session對象的update()方法重新附加User實例嗎?我需要嗎?

回答

1

假設你爲每個請求 - 響應週期創建一個新的Hibernate Session,有可能分離對象合併到新的Hibernate Session,但我會完全避免使用此方法。

而是嘗試存儲上,可用於通過Hibernate來查找用戶的每一個進入的請求HttpSession中的關鍵。如果您擔心訪問數據庫以檢索可以存儲在HttpSession中的某些內容的性能後果,請不要擔心 - 您可以始終使用hibernate支持的緩存框架來減少數據庫訪問次數。提高性能的另一種方法是使用樂觀鎖定。

雖然我沒有看過休眠來源,我覺得Hibernate使用「標識映射」的格局。這是一個Map,它使用實體的ID作爲Map中的鍵和關聯的實體對象作爲Map中的值。每當從休眠會話中檢索實體時,hibernate就會查看會話的身份映射以查看它是否在那裏。如果它在那裏,它將從地圖返回實體。如果不存在,它將從數據庫中檢索實體並將其放在地圖上,然後返回該實體。這意味着,訪問一個給定的用戶使用相同的密鑰的連續查詢(即ID,用戶id等)對於給定的休眠會話將接收到相同的用戶對象的引用,並且因此每個查詢將能夠「看到」到進行修改用戶對象由另一個查詢。出於這個原因,爲每個傳入請求創建一個新的hibernate會話是絕對必要的,這樣對給定用戶的併發請求就不必在其公共User對象上鎖定它們各自的線程。不同的休眠會話將分別擁有自己的身份映射,因此不會返回對同一個用戶對象的引用。

通過嘗試將HttpSession中的用戶對象合併到您的hibernate會話中,您基本上正在嘗試直接操作hibernate的IdentityMap,將任何hibernate「認爲」應該與其他事物相關聯,並且可以理解這會導致問題。正如我所說,雖然可以將分離的對象附加到休眠會話中,但我會避免它。祝你好運,你採取任何方式。

我會強烈建議閱讀以下內容,你的情況特別是部分在長對話和分離對象:對非託管實體

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html

0

取決於如果會話期間用戶改變,或者如果你只是想ID,名稱等進行快速查找。您始終可以將數據庫中的用戶合併()以將其重新放入會話中。

你並不需要合併用戶每次,因爲它,你並不總是需要一個數據庫命中。但通過合併,您可以將用戶重新連接到當前會話。

+1

刷新是個例外!他必須合併。 – Affe 2010-05-29 21:11:02

+0

@Affe:正確。編輯帖子反映了這一點 – Daniel 2010-05-30 17:36:27

相關問題