总是热切地休眠一对一加载

Posted

技术标签:

【中文标题】总是热切地休眠一对一加载【英文标题】:Hibernate one-to-one loads eagerly always 【发布时间】:2016-12-27 17:26:46 【问题描述】:

我有一个具有一对一双向映射的员工和地址:

@Entity
public class Employee 
    @Id
    @Column(name = "EMP_ID")
    private long id;

    private String firstName;
    private String lastName;
    private double salary;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ADDRESS_ID")
    private Address address;

下面是我的地址实体:

@Entity
public class Address 
    @Id
    @Column(name = "ADDRESS_ID")
    private long id;

    private String street;
    private String city;
    private String province;
    private String country;
    private String pinCode;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "address")
    private Employee owner;

在地址中,我将获取类型设置为惰性。因此,如果我得到一个地址,那么我希望 hibernate 只对地址运行选择查询,但我在日志中看到它也在尝试获取 Employee。

以下是我的 HQL 查询:

List<Address> emps = session.createQuery("from Address where id=20").list();

这些是 Hibernate 运行的查询:

Hibernate: 
    /* 
from
    Address 
where
    id=20 */ select
        address0_.ADDRESS_ID as ADDRESS_1_0_,
        address0_.city as city2_0_,
        address0_.country as country3_0_
    from
        Address address0_ 
    where
        address0_.ADDRESS_ID=20
Hibernate: 
    /* load Employee */ select
        employee0_.EMP_ID as EMP_ID1_1_0_,
        employee0_.ADDRESS_ID as ADDRESS_5_1_0_,
        employee0_.firstName as firstNam2_1_0_,
        employee0_.lastName as lastName3_1_0_
    from
        Employee employee0_ 
    where
        employee0_.ADDRESS_ID=?

为什么即使我将其获取策略设置为 LAZY,hibernate 也会急切地加载 Employee。

【问题讨论】:

你可以参考***.com/questions/1444227/…的答案。我认为这篇文章可以帮助你。 【参考方案1】:

这篇很棒的文章描述了问题和可能的解决方案:

https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/

可能的解决方案:必须是从子到父的单向关系。父级不能有一个@OneToOne 字段来访问子级,因为:

"对于每一个托管实体,Persistence Context都需要实体类型和标识符,所以在加载父实体时必须知道子标识符,找到关联的child主键的唯一方法是执行辅助查询。”

第二种解决方案:改用@OneToMany。不要使用@OneToOne,因为它有这个复杂、微妙、古怪的问题。您可以更改代码以仅允许一对一访问,并可选择添加唯一密钥以强制执行 1-1。

【讨论】:

【参考方案2】:

一对一映射的延迟加载可以通过

    设置optional=false(如果它不可为空)或 JoinColumn(不在 PK 上,可能需要更改架构)

您可以参考this链接了解更多信息。

说明:详细说明可以参考explanation link。

【讨论】:

【参考方案3】:

较新版本的休眠不能使用诸如 optional=false 之类的技巧。

查看更新的解决方案best way to map a onetoone relationship

【讨论】:

尝试了 MapsId 的建议,但问题仍然存在:当我调用 Spring 存储库时,正在急切地加载 @OneToOne 参数。听起来像一个休眠错误 “较新版本的hibernate不能使用trick”你有这方面的参考吗?

以上是关于总是热切地休眠一对一加载的主要内容,如果未能解决你的问题,请参考以下文章

一对多和一对多连续映射的休眠条件查询 - 表或视图不存在

渴望/延迟加载的成员总是为空,JPA 一对多关系

休眠中的异常(一对一)

如何使用注释在休眠中进行一对一映射

休眠一对一映射。从依赖表中删除行

使用xml休眠从一个表到多个表的一对一关系