了解Hibernate / JPA对findAll和findOne的不同行为

时间:2015-04-27 16:59:40

标签: hibernate jpa spring-data spring-data-jpa

我正在使用findAll方法(来自Spring Data JPA Repository)调试性能问题,问题是正在使用的获取计划。 (Hibernate正在执行其他选择以检索其他实体而不是使用获取连接)

我的实体与另一个实体有一些关系,我遇到的问题与* ToOne关系有关。

在google上花了一些时间之后,我意识到有一些方法可以管理Hibernate将执行的查询(使用JPA Criteria,NamedEntityGraph,自定义查询......)。

我已经创建了一个小例子来演示不同的行为,但我想理解为什么Hibernate默认会这样做。我花了一些时间在文档中搜索,但我无法找到对此默认行为的任何引用。

https://github.com/pmvilaca/jpa-test

区别:

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

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=?

有什么想法吗?

由于

1 个答案:

答案 0 :(得分:1)

@OneToOne的默认提取类型为FetchType.EAGER。 因此,在没有任何关于如何优化查询的提示的情况下,Hibernate将遵循以下步骤:

选择所有User

Hibernate: 
select
    user0_.id as id1_1_,
    user0_.contact_details_id as contact_3_1_,
    user0_.name as name2_1_ 
from
    user user0_

现在急切地加载每个 User的{​​{1}}和ContactDetails

UserDetails

这通常被称为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=? ... 问题。例如,请参阅here