gpt4 book ai didi

java - 禁用 Hibernate 的递归获取

转载 作者:行者123 更新时间:2023-12-02 08:51:58 24 4
gpt4 key购买 nike

当前堆栈:

  • Spring Boot 1.5.1
  • Spring Data JPA 1.11.0
  • Hibernate 核心 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设置为 null Hibernate 代理 - 正如它应该的那样。

当我打电话getChildren()时Hibernate 正确地初始化了集合,但也(无根据地)获取了每个 Child对象的grandchildren设置。

有人可以准确解释为什么会发生这种递归抓取吗?有没有办法禁用它?

<小时/>

我做了一些更多的挖掘,这就是我想到的:它似乎与 Hibernate 映射的方式有关 @OneToMany取决于目标集合是否是 ListSet .

private final RootRepo repo;

如果集合是 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 -> {});
});
});
}

但是,与 List

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 及其默认实现 @EqualsAndHashCode 生成 getter/setter 等。注释生成两种方法时考虑到每个字段......包括子集合。

最佳答案

我很惊讶 Root 的 child 实际上是空的。

它在您的情况下的工作方式(请仔细检查子项是否实际上设置为空)是,当您访问 getChildren() (例如通过调用 size() ).. 会获取该集合来自数据库及其所有急切的依赖项。

所有惰性依赖项(在本例中为孙子项)都被实例化为 Proxy 对象,但不应在数据库上执行这些查询(请检查)。

另外

这从未发生在我身上,只是一件需要记住的小事。根据 JPA 的说法,延迟加载功能只是对持久性提供程序的提示。即使您将 fetchType 设置为 LAZY 或通常您希望默认情况下延迟加载集合依赖项(可以在配置 session 工厂时完成),实现仍可能决定执行 EAGER fetch:

Defines strategies for fetching data from the database. The EAGER strategy is a requirement on the persistence provider runtime that data must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified.

关于java - 禁用 Hibernate 的递归获取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42116829/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com