【问题标题】:Eager fetching - find vs JPQL渴望获取 - 查找与 JPQL
【发布时间】:2020-03-08 07:12:45
【问题描述】:

我在两个实体(学生和地址)之间存在一对一的关系。

//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

为什么会出现这种差异?

【问题讨论】:

  • 你用的是什么休眠版本?
  • 休眠 5.4.12

标签: hibernate jpa jpql


【解决方案1】:

documentation 中描述的行为。

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

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

如果您忘记 JOIN 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()

【讨论】:

    猜你喜欢
    • 2020-01-20
    • 2014-05-15
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 2014-09-29
    • 2015-03-10
    • 2023-03-09
    • 2016-01-18
    相关资源
    最近更新 更多