为什么 JPA 默认使用 FetchType EAGER 作为@ManyToOne关系
我注意到映射的默认值在JPA和Hibernate中,而对于映射,默认值是。FetchType
@ManyToOne
EAGER
@OneToMany
FetchType
LAZY
这背后的具体原因是什么?
我注意到映射的默认值在JPA和Hibernate中,而对于映射,默认值是。FetchType
@ManyToOne
EAGER
@OneToMany
FetchType
LAZY
这背后的具体原因是什么?
从 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 假定,一般来说,大多数应用程序都要求单例关系缺省急切,而多值关系缺省情况下是惰性的。
请参阅此处了解更多信息
之所以将它们设置为 EAGER,是因为早期的 JPA 1.0 设计人员认为强制执行 JPA 实现以支持动态初始化代理将是一个非常严格的要求。但是,由于没有代理,性能将受到巨大影响,因此所有提供商都支持LAZY关联。
FetchType.EAGER
使用默认的 EAGER 获取策略和关联是一个糟糕的想法,因为您很容易遇到 N+1 个查询问题。@ManyToOne
@OneToOne
使用 Hibernate 时,一旦关联设置为 ,您就不能再在查询时懒惰地获取它。因此,无论当前的业务用例是否需要它,您始终会获取该关系。FetchType.EAGER
FetchType.LAZY
因此,最好默认对所有关联使用。FetchType.LAZY
与 不同,关系可以在查询时使用子句急切地获取。FetchType.EAGER
FetchType.LAZY
JOIN FETCH
您唯一需要注意的是,如果您需要在 JPA 关闭后访问关联,则需要在当前运行的持久性上下文的上下文中获取该关联。否则,您将获得一个懒惰初始化异常
EntityManager