ChatGPT解决这个技术问题 Extra ChatGPT

Hibernate 中一对一、多对一和一对多的默认获取类型

休眠映射中的默认获取类型是什么?

经过一番探索,我了解到:

对于一对一来说,它是渴望的。

对于一对多,它是懒惰的。

但是在 Eclipse 中对其进行了测试后,它对所有人都充满了渴望。

这取决于我使用的是 JPA 还是 Hibernate?

如果您仍然参与 JPA 主题 - 我用新答案更新了您的问题,因为旧答案对于当前的 Hibernate 版本已经过时。

A
Alexander Rühl

这取决于您使用的是 JPA 还是 Hibernate。

JPA 2.0 spec 开始,默认值为:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

在休眠状态下,一切都是懒惰的

更新:

最新版本的 Hibernate 与上述 JPA 默认值一致。


“在休眠状态下,一切都是懒惰的”,显然它在最近的版本中发生了变化。请参阅Alexander Rühl's answer below
Hibernate 是 JPA 实现之一,所以一旦你使用 Hibernate,你就在使用 JPA :)
这是一个流行的查询。 @Ashish Agarwal您能否更新答案的最后一行。在 Hibernate 中,它现在并不懒惰。
更新了有关最新 Hibernate 行为的帖子。
有一个更新,声称 eager 是每个映射的默认获取类型,在当前 5.x 和新的 6.x Hibernate 文档中的第 11.3 章反驳了这一点,所以我撤消了编辑。此外,不具有自动渴望是反对建议的,因为这意味着在获取单个对象时可能会选择整个数据库。
A
Alexander Rühl

我知道在提出问题时答案是正确的 - 但是由于人们(就像我现在一样)仍然碰巧发现他们想知道为什么他们的 WildFly 10 表现不同,我想提供当前 Hibernate 5 的更新.x 版本:

Hibernate 5.2 User Guide 中,它在第 11.2 章中有说明。应用获取策略

Hibernate 的建议是将所有关联静态标记为惰性,并使用动态获取策略来实现渴望。不幸的是,这与 JPA 规范不一致,该规范定义了所有一对一和多对一的关联都应该在默认情况下急切地获取。 Hibernate,作为一个 JPA 提供者,尊重这个默认值。

因此,Hibernate 的行为也类似于上面针对 JPA 所述的 Ashish Agarwal:

OneToMany: LAZY
ManyToOne: EAGER
ManyToMany: LAZY
OneToOne: EAGER

(见JPA 2.1 Spec


如果我们使用原生 hibernate 而不是 JPA impl,它的行为方式是否相同?
@jMounir:嗯,我没有尝试过,但是由于 Hibernate 声明它的行为类似于 JPA 中定义的行为,所以我不明白为什么在单独使用 Hibernate 时会有所不同。在这两种情况下都可以覆盖默认策略。
J
JamesENL

为了回答您的问题,Hibernate 是 JPA 标准的一种实现。 Hibernate 有自己的操作怪癖,但根据 Hibernate docs

默认情况下,Hibernate 对集合使用惰性选择获取,对单值关联使用惰性代理获取。这些默认值对于大多数应用程序中的大多数关联都是有意义的。

因此 Hibernate 将始终使用延迟获取策略加载任何对象,无论您声明了哪种类型的关系。它将为一对一或多对一关系中的单个对象使用惰性代理(应该未初始化但不为空),以及一个空集合,当您尝试访问它时它将与值水合.

应该理解,Hibernate 只会在您尝试访问对象时尝试用值填充这些对象,除非您指定 fetchType.EAGER


J
Jijo Mathew

对于单值关联,即一对一和多对一:- 默认 Lazy=proxy 代理延迟加载:- 这意味着您的关联实体的代理对象已加载。这意味着只为关联实体的代理对象加载连接两个实体的 id。例如:A 和 B 是具有多对一关联的两个实体。即:每个 B 可能有多个 A。A 的每个对象都将包含 B 的引用。`

public class A{
    int aid;
    //some other A parameters;
    B b;
}
public class B{
    int bid;
     //some other B parameters;
}

` 关系 A 将包含列(aid,bid,...实体 A 的其他列)。关系 B 将包含列(出价,...实体 B 的其他列) 代理意味着当获取 A 时,仅获取 B 的 id 并存储到 B 的仅包含 id 的代理对象中。 B 的代理对象是代理类的对象,它是 B 的子类,只有最少的字段。由于bid 已经是关系A 的一部分,因此不必触发查询以从关系B 中获取bid。实体B 的其他属性仅在访问bid 以外的字段时才延迟加载。

对于集合,即多对多和一对多:- 默认 Lazy=true 另请注意,获取策略(选择、加入等)可以覆盖惰性。即:如果lazy='true' 和fetch='join',则获取A 也会获取B 或Bs(如果是集合)。仔细想想就知道原因了。单值关联的默认获取是“join”。集合的默认获取是“选择”。请验证最后两行。我已经从逻辑上推断出来了。