2012-08-28 18 views
0

我正在開發一個需要使用Visual Paradigm的Java項目。 Visual Paradigm使用Hibernate。我的項目運行良好,直到我添加了Genady RMI。我也需要使用RMI。使用Hibernate + RMI「沒有會話或會話已關閉」

在服務器端,我有MainDb,它管理數據庫的所有查詢,在客戶端,我有實現RMI Remote的UserWindow和AdminWindow類。這兩個類通過RMI獲取對象MainDb。據

failed to lazily initialize a collection of role: dcl.UsuarioRegistrado.ORM_TieneVideosFavoritos, no session or session was closed. 

我所知,:

當我運行服務器和客戶端,我已經得到了有關延遲初始化與錯誤的異常「沒有會話或會話已關閉」 Hibernate使用一個不同的會話,從中創建dcl.UsuarioRegistrado對象。問題是我沒有管理會話,因爲PersistentManager類只提供getSession()。 PersistentManager類是VisualParadigm提供​​的用於管理Hibernate的類。

我試過配置lazy =「false」的所有實體,但結果更糟,因爲某些實體的屬性未正確加載。例如,一個對象「Topic」被加載到String屬性「TopicName」爲null。

那麼,我能做些什麼來維持同一個會話呢?

在此先感謝,我非常抱歉,但我可憐的英語。我很難用英語解釋這種情況,所以再次感謝。

+0

'PersistentManager.getSession()'使用'sessionFactory.getCurrentSession()'或'sessionFactory.openSession()'返回會話? –

+0

您使用的C3P0連接池?如果是這樣,嘗試禁用它,看看它是否解決了這個問題。我有一個類似的問題與休眠完整的struts2插件。 – Resh32

+0

@ Resh32它使用C3P0。我可以禁用它刪除中的屬性嗎? – honnix

回答

1

這是一個常見問題。當你在一個實體中有一個集合時,Hibernate會在實例中注入一個「Hibernate-aware」集合。因此,而不是一個列表,你會得到一些記憶當前會話的東西(「當前」=實體加載的會話)。

原因是會話==數據庫事務。如果Hibernate會使用新會話加載相關實體,那麼您可以看到新的行,更新的行,或者您可能會遇到錯誤,因爲在加載父實體時行已經被刪除。這將是一個爛攤子。

爲了確保不會發生這種情況,Hibernate將使用原始會話加載所有相關的實體。但是代碼通常工作不同。在一部分中,您加載了實體。會議閉幕。然後,在一個完全不相關的部分,你嘗試加載兒童 - >錯誤。

有三種解決方案:

  1. 禁用延遲加載。這通常不起作用(加載太多,太慢)。但它不應該導致錯誤;潛在的代碼中可能存在一個bug。

  2. 加載實體時,從每個集合中獲取第一個實體。這將正確初始化收集。這樣做的好處是,您可以在代碼中決定何時加載相關實例以及何時使用依賴Hibernate進行延遲加載。

    你也可以只加載你需要的關係;所以這通常解決了以前的問題。缺點是你需要知道其他代碼將如何使用你的實體預先。這往往很難甚至不可能。

  3. 您可以創建一個新的會話,並使用Session.refresh()「附加」現有的對象到這個新的會話。請注意,您在這裏需要小心;如果你混合刷新和舊對象,你會得到錯誤。

+0

我再次嘗試選項1,果然,錯誤是在我的代碼。糾正了這個錯誤後,我收到了其他幾個錯誤。它們基本上是「具有相同標識符的不同對象」,我不知道如何解決它。 – honnix

+0

可能有很多原因。請接受我的答案,並張貼與你做了什麼細節以及準確的錯誤消息和堆棧跟蹤的新問題。 –