2010-06-29 160 views
5

我目前正在將使用EclipseLink的(工作)應用程序從使用EclipseLink遷移到Hibernate JPA,大部分情況非常順利,但我找到了一件我無法解釋的事情,並且還可以沒有想到任何好的搜索條件!休眠JPA - ManyToOne關係未填充

基本上,我有四個實體,有一個一對多的關係,形成了產業鏈:

EntityA有EntityB的,各自有EntityC的列表,每個都有EntityD的名單列表

那些的每個然後具有許多對一關係走另一條路,這樣:

EntityD具有EntityC,其具有EntityB,其具有EntityA。

即(很大程度上減少清晰度):

@Entity 
public class EntityA { 
    @OneToMany (cascade = CascadeType.All, mappedBy = "entityA") 
    private List<EntityB> entityBList; 
    ... 
} 

@Entity 
public class EntityB { 
    @OneToMany (cascade = CascadeType.All, mappedBy = "entityB") 
    private List<EntityC> entityCList; 

    @JoinColumn (name = "ENTITY_A", referencedColumnName = "ENTITY_A_ID") 
    @ManyToOne (cascade = CascadeType.PERSIST, optional = false) 
    private EntityA entityA; 
} 

@Entity 
public class EntityC { 
    @OneToMany (cascade = CascadeType.ALL, mappedBy = "entityC") 
    private List<EntityD> entityDList; 

    @JoinColumn (name = "ENTITY_B", referencedColumnName = "ENTITY_B_ID") 
    @ManyToOne (cascade = CascadeType.PERSIST, optional = false) 
    private EntityB entityB; 
} 

@Entity 
public class EntityD { 
    @JoinColumn (name = "ENTITY_C", referencedColumnName = "ENTITY_C_ID") 
    @ManyToOne (cascade = CascadeType.PERSIST, optional = false) 
    private EntityC entityC; 
} 

我從數據庫中獲取的EntityA(尋找它通過主鍵),從而得到一個人口很好EntityA例如,用PersistentBag爲我的List<EntityB>。當我解引用List<EntityB>時,我看到一個懶惰的負載發生,並且從EntityB獲取EntityC時重複相同。

在這一點上,一切都如我所料,我有一個EntityA,B和C全部用數據庫中的值填充,但是然後我嘗試從EntityC中獲得我的EntityD,並發現它爲空。

我的實體管理器在這一點上仍然是開放和活躍的,即使我在獲得EntityA後立即在調試器中查看它,我可以遍歷關係,直至EntityC,並再次查看'entityDList '爲空。

我到目前爲止發現的唯一的解決辦法是使用:

EntityManager.refresh(entityC); 

其中填充的所有元素,包括一個懶洋洋地加載PersistentBag爲entityDList。因此,我的猜測是,Hibernate只填充參考2級深(或3,取決於你如何計數),並放棄後,雖然我不明白爲什麼會這樣。這對任何人都有意義嗎?

除了.refresh之外,還有其他解決方案嗎?某種配置或註釋值會使Hibernate一直向下填充引用?

+0

爲hibernate配置參數「max_fetch_depth」設置了什麼值? – 2010-07-06 14:48:10

回答

2

感謝來自這裏的人的建議,這些建議可能是相關的,但沒有幫助我的具體情況。

如果您在閱讀時遇到同樣的問題,可能值得嘗試使用max_fetch_depth建議,但由於某種原因,它不適用於我(我喜歡爲什麼會提供建議?)。同樣,如果你的@ OneToMany是集合,而不是列表,按Albert建議的那樣做一個急切的獲取或左連接,但顯然Hibernate只允許你最多有1個熱切獲取的列表,如果你需要更多,你的集合應該是集合。我沒有嘗試,但我懷疑它可能解決了這個問題。

除非任何人有更好的建議,否則我會堅持調用刷新,無論如何,這實際上可能對我的應用程序更有意義。

1

確實很有趣。解決這個問題的一種方法是查詢對象A的左連接 - 抓取到 - > B-> C-> D,如果你還要遍歷到對象D,它也會更快。 這將是這樣的。

"from A left join fetch B left join fetch C left join fetch D" 

您是否嘗試過從C-> D渴望?好奇會發生什麼,然後...

+0

謝謝艾伯特,我嘗試了兩個建議,但沒有結果:(使關係渴望沒有效果,所以我試圖使所有3個關係(A-> B-> C-> D)渴望,但休眠抱怨「不能同時取多個行李「。向JPQL添加左連接的結果是相同的 我在其他地方發現了一些建議,這是因爲我急於提取的集合是列表,並且如果我將它們設置爲集合,它會起作用,但我現在懶得這樣做,所以我想我會忍受一個刷新調用! – DaveyDaveDave 2010-07-07 16:47:56

1

hibernate文檔說,你可以使用hibernate.max_fetch_depth屬性來設置它。默認值是3.您可以在第47頁上的"Hibernate Reference Documentation"中找到它。

+0

感謝您 - 你知道,如果hibernate.properties文件也被Hibernate JPA使用,我找不到在Hibernate文檔中的任何地方都有答案?我已經嘗試將它改爲4並且也是0,並且它似乎沒有效果... – DaveyDaveDave 2010-07-07 15:54:40

+0

好吧,忽略上述內容,似乎正在使用它,因爲通過將max_fetch_depth設置爲0已打破我的應用程序的其他部分:)雖然它設置爲一個很高的數字(我試過4和10),似乎沒有任何效果;我猜是因爲這只是一個最大值,而其他的則是說服Hibernate停止在3個級別......? – DaveyDaveDave 2010-07-07 16:04:47