当前筹码:
假设我们有以下@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
集。
有人可以解释为什么会发生这种递归提取并且有没有办法禁用它?
我做了一些挖掘,这就是我提出的:它似乎与Hibernate映射@OneToMany
的方式有关,具体取决于目标集合是List
还是{{1} }。
Set
如果集合是private final RootRepo repo;
s
Set
然而,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 -> {});
});
});
}
s
List
我是一名可认证的白痴。
我正在使用Lombok为我的 POJO 生成getter / setter等,其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_
});
});
});
}
注释的默认实现会生成考虑每个字段的两种方法..包括子集合
答案 0 :(得分:0)
我很惊讶Root的孩子实际上是空的。
它在你的情况下的工作方式(请仔细检查子项是否实际设置为null),是当你访问getChildren()时(例如通过调用size())..那个集合被获取来自数据库及其所有渴望的依赖项。
所有延迟依赖项(在这种特殊情况下都是孙子)都被实例化为Proxy对象,但是对于那些应该没有对数据库执行sql查询(请检查)。
<强>另外强>
它从来没有发生在我身上,但只是要记住一点......根据JPA,延迟加载功能只是对持久性提供程序的提示。即使您将fetchType设置为LAZY,或者通常您希望默认情况下延迟加载您的集合依赖项(可以在配置会话工厂时完成),实现仍可能决定执行EAGER提取:
定义从数据库中获取数据的策略。 EAGER 策略是持久性提供程序运行时的要求 必须急切地获取数据。 LAZY策略是一个提示 持久性提供程序运行时,应该在延迟时获取数据 它是第一次访问。允许实施急切地获取 已指定LAZY策略提示的数据。