渴望获取-查找与JPQL



我在两个实体之间有一对一的关系——学生和地址。

//Student
@OneToOne(fetch = EAGER)
@JoinColumn(name = "ADDRESS_ID")
private Address address;

调用entityManager.find(Student.class, 1)导致ADDRESS按预期被急切地提取:

Hibernate: 
select
student0_.id as id1_4_0_,
student0_.address_id as address_7_4_0_,
student0_.crt_ts as crt_ts2_4_0_,
student0_.email as email3_4_0_,
student0_.first_name as first_na4_4_0_,
student0_.last_name as last_nam5_4_0_,
student0_.upd_ts as upd_ts6_4_0_,
address1_.id as id1_1_1_,
address1_.city as city2_1_1_,
address1_.state as state3_1_1_,
address1_.street as street4_1_1_,
address1_.zip as zip5_1_1_ 
from
t_student student0_ 
left outer join
t_address address1_ 
on student0_.address_id=address1_.id 
where
student0_.id=1

但是,调用

String query = "select s from Student s where s.id=1";
return entityManager.createQuery(query, Student.class).getSingleResult();

不会触发ADDRESS:的紧急获取

Hibernate: 
select
student0_.id as id1_4_,
student0_.address_id as address_7_4_,
student0_.crt_ts as crt_ts2_4_,
student0_.email as email3_4_,
student0_.first_name as first_na4_4_,
student0_.last_name as last_nam5_4_,
student0_.upd_ts as upd_ts6_4_ 
from
t_student student0_
where
student0_.id=1

为什么会出现这种差异?

文档中描述的行为。

如果使用的实体查询不包含JOIN FETCH指令,Hibernate将使用辅助选择。

这是因为实体查询获取策略不能被覆盖,所以Hibernate需要一个辅助选择,以确保在将结果返回给用户之前获取EAGER关联。

如果您忘记加入FETCH所有EAGER关联,Hibernate将为每一个关联发出二次选择,这反过来会导致N+1查询问题。

出于这个原因,你应该更喜欢LAZY协会。

因此,您可以通过以下方式修复查询:

entityManager.createQuery(
"select s from Student s left join fetch s.address where s.id = :id",
Student.class
)
.setParameter("id", id)
.getSingleResult()

最新更新