为什么 JPA 默认使用 FetchType EAGER 作为@ManyToOne关系

2022-09-02 05:21:57

我注意到映射的默认值在JPA和Hibernate中,而对于映射,默认值是。FetchType@ManyToOneEAGER@OneToManyFetchTypeLAZY

这背后的具体原因是什么?


答案 1

JPA 2.0 spec 开始,默认值如下所示:

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

冬眠中,一切都是懒惰的

来自 Hibernate Docs,

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

为了回答你的问题,Hibernate是JPA标准的实现。Hibernate有自己的操作怪癖,但根据Hibernate文档

By default, Hibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.

因此,Hibernate 将始终使用延迟获取策略加载任何对象,无论您声明了哪种类型的关系。

JPA Spec 假定,一般来说,大多数应用程序都要求单例关系缺省急切,而多值关系缺省情况下是惰性的。

请参阅此处了解更多信息


答案 2

JPA gotcha

之所以将它们设置为 EAGER,是因为早期的 JPA 1.0 设计人员认为强制执行 JPA 实现以支持动态初始化代理将是一个非常严格的要求。但是,由于没有代理,性能将受到巨大影响,因此所有提供商都支持LAZY关联。

避免FetchType.EAGER

使用默认的 EAGER 获取策略和关联是一个糟糕的想法,因为您很容易遇到 N+1 个查询问题@ManyToOne@OneToOne

使用 Hibernate 时,一旦关联设置为 ,您就不能再在查询时懒惰地获取它。因此,无论当前的业务用例是否需要它,您始终会获取该关系。FetchType.EAGER

默认使用FetchType.LAZY

因此,最好默认对所有关联使用。FetchType.LAZY

与 不同,关系可以在查询时使用子句急切地获取。FetchType.EAGERFetchType.LAZYJOIN FETCH

您唯一需要注意的是,如果您需要在 JPA 关闭后访问关联,则需要在当前运行的持久性上下文的上下文中获取该关联。否则,您将获得一个懒惰初始化异常EntityManager


推荐