Стремитесь к поиску - найдите против JPQL - PullRequest
1 голос
/ 08 марта 2020

У меня взаимно-однозначное отношение между двумя объектами - Студентом и Адресом.

//Student

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

Вызов entityManager.find(Student.class, 1) приводит к АДРЕСУ, ожидаемому с нетерпением:

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

Почему происходит это несоответствие?

1 Ответ

1 голос
/ 08 марта 2020

Поведение, которое вы видите, описано в документации .

Если вы используете запрос сущности, который не содержит директивы JOIN FETCH, Hibernate использует вторичный выбор.

Это связано с тем, что политику выборки запросов сущностей нельзя переопределить, поэтому Hibernate требует вторичного выбора, чтобы убедиться, что привязка EAGER извлекается до возврата результата пользователю.

Если вы забыли Чтобы присоединиться ко всем ассоциациям 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()

...