2010-06-29 112 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