2012-10-26 71 views
3

我有以下JSF/PrimeFaces EJB體系結構:JSF/EJB3避免視圖層延遲初始化異常

[JSF/PrimeFaces XHTML視圖] - > [@ManagedBean JSF豆] - > [@Stateless EJB3豆] --JPA - > [DB]

也就是說,JSF視圖顯示實體與集合,他們對他們的支持豆(@ManagedBean)和這些集合和實體訪問被依次取出通過調用無狀態EJB3注入了EntityManager的「外觀」bean,並使用訪問數據庫JPA支持休眠。無狀態的EJB3還提供了一些服務,但其大部分作用是根據需要顯示它們的xhtml視圖請求,從數據庫提供實體對象(JPA -annotated)。

現在是這樣的:如果我的理解是正確的,那麼無狀態EJB3 bean返回實體Bean的時候,它們就會分開,因爲每個bean都會分開一個事務處理Bean3D方法。然後,經常出現這樣的情況:在訪問這些實體對象的圖表(一對多集合等)時,我經常會遇到如下的延遲初始化異常:

javax.el.ELException: ... org.hibernate.LazyInitializationException: failed 
to lazily initialize a collection of role: ..., no session or session was closed 

,工程正在改變收藏的唯一的事情是EAGER -ly加載,但是這不是一個務實的解決方案。當分離的JPA實體找到訪問視圖層的方式時,爲了避免一勞永逸地避免初始化異常,而不是以特定方式處理每個案例,有什麼好的模式可供使用?

+2

您是否嘗試Hibernate.initialize(代理)來初始化該字段? http://docs.jboss.org/hibernate/orm/3.5/api/org/hibernate/Hibernate.html#initialize(java.lang.Object) – 757071

+1

爲什麼這與在一對一中指定FetchType.EAGER不同 - 多收集? –

回答

4

處理延遲關聯有兩種方法。第一種方法是使用以下初始化實體:

Hibernate.initialize(proxy) 

或者將獲取類型設置爲EAGER,當您加載它時將獲取整個實體。 第二個也是更正確的方法(在我看來)是隻要你保留實體就保留實體管理器。這可以通過使用這樣的@Stateful會話做到無論:

@Stateful 
public class UserService { 
    @PersistenceContext(type=EXTENDED) 
    private EntityManager entityManager; 

    ...... the business method 
} 

,並保持對EJB的引用,只要你保持實體。有關擴展持久性上下文的更多信息,請參見here。 保持實體管理器的其他方法是使用CDI模塊,如seam-persistenceCODI,它們提供了創建EntityManager並保持對話範圍的功能。