我想热切地填充我的对象层次结构。问题是,在某些时候,Hibernate会停止提取;它使关系字段(列表)无人居住。
层次结构是(某些代码被省略,就像id,getters一样,这部分看起来很好,希望如此):
public class User {
private Container container;
@OneToOne(fetch = FetchType.EAGER)
public Container getContainer() {
return container;
}
}
public class Container {
private List<Backpack> backpacks;
private List<Item> items;
@OneToMany(fetch = FetchType.EAGER, mappedBy="container")
@Fetch(FetchMode.SELECT)
private List<Item> getItems() {
return items;
}
@OneToMany(fetch = FetchType.EAGER, mappedBy="container")
@Fetch(FetchMode.SELECT)
private List<Backpack> getBackpacks() {
return backpacks;
}
}
public class Backpack {
...
private Container container; /* Unidirectional relationship - ID of container which contains this backpack */
private Container backpackContainer; /* Unidirectional relationship - ID of container which represents backpack's storge */
...
@NotNull
@ManyToOne(fetch = FetchType.EAGER)
@Fetch(FetchMode.SELECT)
public Container getContainer() {
return container;
}
@OneToOne(fetch = FetchType.EAGER)
@Fetch(FetchMode.SELECT)
public Container getBackpackContainer() {
return backpackContainer;
}
}
结果:
User(
uid=2,
name=admin,
....,
container=Container(
id=1,
items=[
Item(...),
Item(...),
Item(...),
Item(...)
],
backpacks=[
Backpack(
container=1,
backpackContainer=Container(
id=3,
items=null, /* Problem! Shouldn't be empty array [] at least or array with items? */
backpacks=null /* Problem! Shouldn't be empty array [] at least or array with backpacks? */
)
)
]
)
)
当我注释结果时,嵌套字段项和背包为空,这表明存在一个巨大的问题。 Hibernate倾向于使用空集而不是空值,我也不想在任何地方添加空检查器。
什么可能导致这个问题?
此外,这个层次结构不是无限深,用户的容器可能有它想要的背包,但那些背包可能不包含其他背包。
答案 0 :(得分:1)
唯一合乎逻辑的解释是,您正在同一个持久化上下文(会话)中读取User
图,其中您已经保存了一个包含空值的新(临时)Container
实例,该实例已分配给<{1}}之后加载和组装backpackContainer
图表时的User
参考。
在保存实例时,Hibernate不会填充关联,但是在从db加载实例时会执行此操作,因此您使用null创建了它,并且它在持久性上下文中仍然存在。当您之后阅读User
图表时,Hibernate会重用持久化上下文中当前存在的所有内容,包括它分配给Container
字段的backpackContainer
实例。
所以,你有两个选择:
或者只需在阅读User
之前刷新并清除持久性上下文(如果您希望在同一事务中发生所有事情):
entityManager.flush();
entityManager.clear();