为了账号安全,请及时绑定邮箱和手机立即绑定

JPA渴望获取未加入

JPA渴望获取未加入

忽然笑 2019-11-22 15:56:34
JPA的提取策略究竟控制什么?我无法发现渴望与懒惰之间的任何区别。在这两种情况下,JPA / Hibernate都不会自动加入多对一关系。示例:人员有一个地址。一个地址可以属于许多人。JPA注释的实体类如下所示:@Entitypublic class Person {    @Id    public Integer id;    public String name;    @ManyToOne(fetch=FetchType.LAZY or EAGER)    public Address address;}@Entitypublic class Address {    @Id    public Integer id;    public String name;}如果我使用JPA查询:select p from Person p where ...JPA / Hibernate生成一个SQL查询以从Person表中进行选择,然后为每个人进行不同的地址查询:select ... from Person where ...select ... from Address where id=1select ... from Address where id=2select ... from Address where id=3这对于大型结果集非常不利。如果有1000个人,它将生成1001个查询(“个人1”和“地址1000”)。我知道这是因为我正在查看MySQL的查询日志。据我了解,将地址的获取类型设置为热切会导致JPA / Hibernate自动进行联接查询。但是,无论获取类型如何,它仍然会为关系生成不同的查询。只有当我明确告诉它要加入时,它才真正加入:select p, a from Person p left join p.address a where ...我在这里想念什么吗?现在,我必须手动编写每个查询的代码,以使它离开连接多对一关系。我正在将Hibernate的JPA实现与MySQL配合使用。编辑:它看起来(不会在这里和这里看到Hibernate FAQ )FetchType不会影响JPA查询。因此,就我而言,我已明确告诉它要加入。
查看完整描述

3 回答

?
墨色风雨

TA贡献1853条经验 获得超6个赞

fetchType属性控制在获取主要实体时是否立即获取带注释的字段。它不一定指示如何构造fetch语句,实际的sql实现取决于您使用的toplink / hibernate等提供程序。

如果设置,fetchType=EAGER则表示带注释的字段将与实体中的其他字段同时填充其值。因此,如果您打开一个entitymanager来检索您的人员对象,然后关闭该entitymanager,则随后执行person.address不会导致引发延迟加载异常。

如果设置fetchType=LAZY,则仅在访问该字段时填充该字段。如果您已经关闭了entitymanager,那么如果执行person.address,则会引发延迟加载异常。要加载该字段,您需要使用em.merge()将实体放回entermangers上下文中,然后进行字段访问,然后关闭entitymanager。

在构造带有客户订单集合的客户类时,您可能需要延迟加载。如果要获取客户列表时检索了客户的每个订单,则仅查找客户名称和联系方式时,这可能是一项昂贵的数据库操作。最好将数据库访问权限保留到以后。

对于问题的第二部分-如何使休眠以生成优化的SQL?

Hibernate应该允许您提供有关如何构造最有效查询的提示,但我怀疑您的表构造有问题。表格中是否建立了关系?Hibernate可能已经决定,简单查询比连接查询要快,尤其是在缺少索引等的情况下。


查看完整回答
反对 回复 2019-11-22
  • 3 回答
  • 0 关注
  • 332 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信