Understand the different Hibernate / JPA behavior for findAll and findOne
I was debugging a performance issue using the findAll method (from the JPA Spring Data Repository) and the problem was using the fetch plan that was used. (Hibernate did additional Selects to fetch additional objects instead of using a fetch connection)
My object has some relationship with other objects and the problem I am facing is with * ToOne relationships.
After spending some time on google, I realized that there are ways to manage queries that Hibernate will execute (using JPA criteria, NamedEntityGraph, custom queries, ...).
I have created a small example demonstrating different types of behavior, but I would like to understand why Hibernate does this by default . I've spent some time searching through the docs, but I couldn't find a link to this default behavior.
https://github.com/pmvilaca/jpa-test
Difference:
Hibernate:
SELECT
user0_.id AS id1_1_0_,
userdetail1_.id AS id1_21_,
contactdet2_.id AS id1_0_2_,
user0_.contact_details_id AS contact_3_1_0_,
user0_.name AS name2_1_0_,
userdetail1_.nationality AS national2_2_1_,
userdetail1_.user_id AS user_id3_2_1_,
contactdet2_.email AS email2_0_2_,
contactdet2_.mobile AS mobile3_0_2_
FROM user user0_
LEFT OUTER JOIN user_details userdetail1_ ON user0_.id = userdetail1_.user_id
LEFT OUTER JOIN contact_details contactdet2_ ON user0_.contact_details_id = contactdet2_.id
and
Hibernate: select user0_.id as id1_1_, user0_.contact_details_id as contact_3_1_, user0_.name as name2_1_ from user user0_
Hibernate: select contactdet0_.id as id1_0_0_, contactdet0_.email as email2_0_0_, contactdet0_.mobile as mobile3_0_0_ from contact_details contactdet0_ where contactdet0_.id=?
Hibernate: select userdetail0_.id as id1_2_2_, userdetail0_.nationality as national2_2_2_, userdetail0_.user_id as user_id3_2_2_, user1_.id as id1_1_0_, user1_.contact_details_id as contact_3_1_0_, user1_.name as name2_1_0_, contactdet2_.id as id1_0_1_, contactdet2_.email as email2_0_1_, contactdet2_.mobile as mobile3_0_1_ from user_details userdetail0_ left outer join user user1_ on userdetail0_.user_id=user1_.id left outer join contact_details contactdet2_ on user1_.contact_details_id=contactdet2_.id where userdetail0_.user_id=?
Hibernate: select contactdet0_.id as id1_0_0_, contactdet0_.email as email2_0_0_, contactdet0_.mobile as mobile3_0_0_ from contact_details contactdet0_ where contactdet0_.id=?
Hibernate: select userdetail0_.id as id1_2_2_, userdetail0_.nationality as national2_2_2_, userdetail0_.user_id as user_id3_2_2_, user1_.id as id1_1_0_, user1_.contact_details_id as contact_3_1_0_, user1_.name as name2_1_0_, contactdet2_.id as id1_0_1_, contactdet2_.email as email2_0_1_, contactdet2_.mobile as mobile3_0_1_ from user_details userdetail0_ left outer join user user1_ on userdetail0_.user_id=user1_.id left outer join contact_details contactdet2_ on user1_.contact_details_id=contactdet2_.id where userdetail0_.user_id=?
Hibernate: select userdetail0_.id as id1_2_2_, userdetail0_.nationality as national2_2_2_, userdetail0_.user_id as user_id3_2_2_, user1_.id as id1_1_0_, user1_.contact_details_id as contact_3_1_0_, user1_.name as name2_1_0_, contactdet2_.id as id1_0_1_, contactdet2_.email as email2_0_1_, contactdet2_.mobile as mobile3_0_1_ from user_details userdetail0_ left outer join user user1_ on userdetail0_.user_id=user1_.id left outer join contact_details contactdet2_ on user1_.contact_details_id=contactdet2_.id where userdetail0_.user_id=?
Any idea?
thank
source to share
The default fetch type for @OneToOne
: FetchType.EAGER . Therefore, without any hint of query optimization, Hibernate will perform the following steps:
Select all User
's:
Hibernate:
select
user0_.id as id1_1_,
user0_.contact_details_id as contact_3_1_,
user0_.name as name2_1_
from
user user0_
Now eagerly download each User
ContactDetails
andUserDetails
Hibernate:
select
contactdet0_.id as id1_0_0_,
contactdet0_.email as email2_0_0_,
contactdet0_.mobile as mobile3_0_0_
from
contact_details contactdet0_
where
contactdet0_.id=?
Hibernate:
select
userdetail0_.id as id1_2_2_,
userdetail0_.nationality as national2_2_2_,
userdetail0_.user_id as user_id3_2_2_,
user1_.id as id1_1_0_,
user1_.contact_details_id as contact_3_1_0_,
user1_.name as name2_1_0_,
contactdet2_.id as id1_0_1_,
contactdet2_.email as email2_0_1_,
contactdet2_.mobile as mobile3_0_1_
from
user_details userdetail0_
left outer join
user user1_
on userdetail0_.user_id=user1_.id
left outer join
contact_details contactdet2_
on user1_.contact_details_id=contactdet2_.id
where
userdetail0_.user_id=?
...
This is commonly referred to as a problem n + 1
. See here .
source to share