我想急切地填充我的对象层次结构。问题是 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 倾向于使用空集而不是 null,我也不想到处添加 null 检查器。
什么可能导致此问题?
此外,这个层次结构并不是无限深的,用户的容器可以有任意数量的背包,但这些背包可能不包含其他背包。
最佳答案
唯一合乎逻辑的解释是,您正在同一个持久性上下文( session )中读取 User
图,在该持久性上下文中您保存了一个新的( transient )Container
实例,其中包含随后加载和组装 User
图时分配给 backpackContainer
引用的 nulls。
Hibernate 在保存实例时不会填充关联,但它会在从数据库加载实例时填充关联,因此您使用 null 来创建它,并且它在持久性上下文中仍然如此。当您随后阅读 User
图时,Hibernate 会重用持久化上下文中当前存在的所有内容,包括它分配给 backpackContainer
的 Container
实例字段。
所以,你有两个选择:
- 如果您确实打算在同一个持久性上下文中使用双向关系的两侧(更简洁的方法),请更新双向关系的两侧;
或者在读取
用户
之前简单地刷新并清除持久性上下文(如果您希望所有事情都发生在同一个事务中):entityManager.flush(); entityManager.clear();
关于java - 急切获取嵌套(递归)对象 - Hibernate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44596690/