当前堆栈:
- 春季启动 1.5.1
- Spring Data JPA 1.11.0
- 休眠核心 5.2.6
假设我们有以下@Entity
结构
@Entity
class Root {
@Id
private Long id;
@OneToMany
@JoinColumn(name = "root_id")
private Set<Child> children
}
@Entity
class Child {
@Id
private Long id;
@OneToMany
@JoinColumn(name = "child_id")
private Set<Grandchild> grandchildren;
}
@Entity
class Grandchild {
@Id
private Long id;
}
当我查询所有/特定Root
对象时,Hibernate 仅从相应的表中选择,结果对象的children
Set 是一个 Hibernate 代理 - 它应该是。null
当我调用getChildren()
Hibernate 正确初始化集合但也(无根据地)获取每个Child
对象的grandchildren
Set。
有人可以准确解释为什么会发生这种递归提取,有没有办法禁用它?
我做了更多的挖掘,这就是我想出的:它似乎与 Hibernate 映射的方式有关,@OneToMany
具体取决于目标集合是 aList
还是Set
.
private final RootRepo repo;
如果集合是Set
s
public void test() {
List<Root> all = repo.findAll(); // SELECT root0_.* FROM root root0_
all.forEach(root -> {
System.out.println(root.getChildren() == null); // false
System.out.println(Hibernate.isInitialized(root.getChildren())); // false
root.getChildren().forEach(child -> {
// SELECT child0_.* FROM children child0_
// SELECT grandchild0_.* FROM grandchildren grandchild0_
System.out.println(child.getGrandchildren() == null); // false
System.out.println(Hibernate.isInitialized(child.getGrandchildren())); // true
child.getGrandChildren().forEach(grandchild -> {});
});
});
}
然而,随着List
s
public void test() {
List<Root> all = repo.findAll(); // SELECT root0_.* FROM root root0_
all.forEach(root -> {
System.out.println(root.getChildren() == null); // false
System.out.println(Hibernate.isInitialized(root.getChildren())); // false
root.getChildren().forEach(child -> {
// SELECT child0_.* FROM children child0_
System.out.println(child.getGrandchildren() == null); // false
System.out.println(Hibernate.isInitialized(child.getGrandchildren())); // false
child.getGrandChildren().forEach(grandchild -> {
// SELECT grandchild0_.* FROM grandchildren grandchild0_
});
});
});
}
我是一个可以证明的白痴。
我正在使用 Lombok 为我的POJO生成 getter/setter 等,其注释的默认实现会@EqualsAndHashCode
生成这两种方法,同时考虑到每个字段......包括子集合。