我有一个 Employee 和 Address 一对一的双向映射:
@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;
}
Run Code Online (Sandbox Code Playgroud)
以下是我的地址实体:
@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;
}
Run Code Online (Sandbox Code Playgroud)
在地址中,我将获取类型设置为懒惰。因此,如果我得到一个地址,那么我希望 hibernate 只对地址运行选择查询,但我在日志中看到它也试图获取 Employee。
以下是我的 HQL 查询:
List<Address> emps = session.createQuery("from Address where id=20").list();
Run Code Online (Sandbox Code Playgroud)
这些是 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=?
Run Code Online (Sandbox Code Playgroud)
为什么即使我将其获取策略设置为 LAZY,hibernate 也会急切地加载 Employee。
这篇很棒的文章描述了这个问题和一个可能的解决方案:
https://vladmihalcea.com/the-best-way-to-map-a-onetoone-relationship-with-jpa-and-hibernate/
可能的解决方案:它必须是从孩子到父母的单向关系。父级不能有一个@OneToOne字段来访问子级,因为:
“对于每个托管实体,Persistence Context 都需要实体类型和标识符,因此在加载父实体时必须知道子标识符,而找到关联的 {child} 主键的唯一方法是执行辅助查询.”
第二种解决方案:@OneToMany改用。不要使用,@OneToOne因为它有这个复杂、微妙、古怪的问题。您可以更改代码以仅允许一对一访问,并可选择添加唯一密钥以强制执行 1-1。
| 归档时间: |
|
| 查看次数: |
5709 次 |
| 最近记录: |