问题描述
我有一个员工和地址,具有一对一的双向映射:
I have an Employee and Address with one-to-one bi-directional mapping:
@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;
}
在地址"中,我已将提取类型"设置为惰性".因此,如果我得到一个地址,那么我期望冬眠只对地址运行选择查询,但是我在日志中看到它也在尝试获取Employee.
In Address I have set Fetch type as Lazy. So if I get an address then I am expecting hibernate to run select query on address only, but I see in logs that it is trying to get Employee also.
以下是我的HQL查询:
Below is my HQL query:
List<Address> emps = session.createQuery("from Address where id=20").list();
这些是Hibernate运行的查询:
These are the queries run by 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,冬眠也会热切地加载Employee.
Why hibernate loads Employee eagerly even when I set its fetching strategy as LAZY.
推荐答案
这篇很棒的文章介绍了该问题和可能的解决方案:
This great article describes the problem and a possible solution:
https: //vladmihalcea.com/与jpa-and-hibernate/
可能的解决方案:它必须是从子代到父代的单向关系.父级不能具有@OneToOne
字段来访问子级,因为:
Possible solution: It must be a one-directional relationship from child to parent. The parent cannot have a @OneToOne
field to access the child because:
对于每个受管实体,持久性上下文都需要实体类型和标识符,因此在加载父实体时必须知道子标识符,而找到关联的{child}主键的唯一方法是执行次要查询."
"For every managed entity, the Persistence Context requires both the entity type and the identifier, so the child identifier must be known when loading the parent entity, and the only way to find the associated {child} primary key is to execute a secondary query."
第二个解决方案:改为使用@OneToMany
.不要使用@OneToOne
,因为它有这个复杂,细微,古怪的问题.您可以更改代码以仅允许一对一访问,并可以选择添加唯一密钥以强制执行1-1.
Second solution: Use @OneToMany
instead. Don't use @OneToOne
because it has this complicated, subtle, quirky problem. You can alter the code to only allow one-to-one access and optionally add a unique key to enforce 1-1.
这篇关于始终热切地休眠一对一负载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!