Reputation: 614
I have a one-to-one relationship between two entities - Student and Address.
//Student
@OneToOne(fetch = EAGER)
@JoinColumn(name = "ADDRESS_ID")
private Address address;
Invoking entityManager.find(Student.class, 1)
results in ADDRESS eagerly fetched as expected:
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
But, invoking
String query = "select s from Student s where s.id=1";
return entityManager.createQuery(query, Student.class).getSingleResult();
does not trigger eager fetching of 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
Why is this discrepancy happening?
Upvotes: 1
Views: 484
Reputation: 13111
The behavior that you see described in the documentation.
If you are using an entity query that does not contain a
JOIN FETCH
directive Hibernate uses a secondary select.This is because the entity query fetch policy cannot be overridden, so Hibernate requires a secondary select to ensure that the EAGER association is fetched prior to returning the result to the user.
If you forget to JOIN FETCH all EAGER associations, Hibernate is going to issue a secondary select for each and every one of those which, in turn, can lead to N+1 query issues.
For this reason, you should prefer LAZY associations.
So, you can fix your query in the following way:
entityManager.createQuery(
"select s from Student s left join fetch s.address where s.id = :id",
Student.class
)
.setParameter("id", id)
.getSingleResult()
Upvotes: 1