2011-07-26 106 views
1

集合我怕我會錯過一個非常基本的觀點,但我堅持的那一刻,希望有人能在這點我的眼睛主演硬到正確的選擇。 我嘗試通過我的應用程序設置一步一步,讓自己清晰(希望人們不會在他們到達發佈結束前感到無聊):異常而加載懶洋洋地從實體

我有一個會話作用域CDI組件作爲JSF處理程序2.0視圖。它擁有一個實體管理器,對象列表和一個特殊的單個對象:

Query query = em.createQuery("select e from MyEvent e"); 
events = (ArrayList<MyEvent>) query.getResultList(); 

@Named 
@SessionScoped 
public class EventHandler implements Serializable { 

    @PersistenceContext 
    private EntityManager em; 

    private List<MyEvent> events; 

    private MyEvent currentEvent; 
    ... 

當視圖請求列表中顯示的表,它通過查詢數據庫填充列表該視圖顯示了這種在一個數據表,並提供該處理程序中的鏈接到動作方法:

<h:dataTable value="#{eventHandler.events}" var="_var"> 
    ... 
    <h:commandLink action="#{eventHandler.linkAction(_var)}"> ... </h:commandLink> 

動作方法存儲參考:

public void setCurrentEvent(MyEvent currentEvent) { 
    this.currentEvent = currentEvent; 
    ... 

內蒐集和上述文獻中使用的實體,它會直接默認延遲加載there'a關係:

@ManyToMany(mappedBy="supportedServices") 
public Set<MyEntity> getSupportingEntities() { 
    ... 

現在,在詳細視圖是和試圖訪問這個關係時這樣做的:

#{eventHandler.currentEvent.supportingEntities...} 

我得到一個org.hibernate.LazyInitializationException告訴我,會話關閉。

不宜處理程序能夠裝載在第二視圖稍後的請求的關係,當處理程序是會話範圍,並通過加載查詢的引用?

回答

1

嗯,我想這是因爲persistenceContext,事件,如果它是一個會話的成員範圍的bean,不會話範圍。
當視圖被稱爲第一時間,創建一個持久上下文,實體(事件)被加載並填充數據表。然後持久化上下文被刷新,關閉並且響應被髮送到客戶端。這一切都發生在同一個http請求中。

但是當你調用細節來看,另一個HTTP請求發出,並創建另一個持久化上下文,和你提到「currentEvent」沒有更多的附加在最後的持久化上下文。因此,LazyInitializationError(該實體必須進行管理,以延遲加載)。

解決方案可能是:

  • 使用擴展的持久化上下文(explained here)。
  • 渴望獲取的關係:

    @ManyToMany(mappedBy="supportedServices", fetch=FetchType.EAGER)

  • 合併currentEvent的脫管的實例在細節上使用它之前查看:

    entityManager.merge(currentEvent);

+0

謝謝你的提示。但是既沒有使用type = PersistenceContextType.EXTENDED,也沒有將它合併到em中,而且在映射中使用預先獲取是不成問題的。但是我看到,如果我在動作處理程序中設置currentEvent時觸及關係,它就會起作用。不過,我不明白爲什麼他們以後不能加載實體的一部分。 –

+0

因爲我還找不到其他解釋,我會接受你的答案。 –

相關問題