Hibernate总是一对一地加载

时间:2016-12-27 17:26:47

标签: java hibernate

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

@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;
}

在地址中我将Fetch类型设置为Lazy。所以,如果我得到一个地址,那么我希望hibernate只在地址上运行select查询,但我在日志中看到它也试图获得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。

3 个答案:

答案 0 :(得分:3)

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

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

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

“对于每个管理实体,持久性上下文都需要实体类型和标识符,因此在加载父实体时必须知道子标识符,而找到关联的{child}主键的唯一方法是执行次要查询。”

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

答案 1 :(得分:1)

可以通过

进行一对一映射的延迟加载
  1. 设置optional=false(如果不可为空)或
  2. JoinColumn(不在PK上,可能需要架构更改)
  3. 您可以参考this链接获取更多信息。

    说明:有关此问题的详细说明,请参阅explanation link

答案 2 :(得分:0)

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

签出更新的解决方案best way to map a onetoone relationship