【问题标题】:Hibernate is much faster when executing a native query执行本机查询时,Hibernate 更快
【发布时间】:2009-12-03 19:51:08
【问题描述】:

以下查询应该返回大约 800 个对象。问题是hibernate实际上执行了800个查询来获取它们。它似乎执行一个查询以获取 id,然后为每个对象执行一个查询以获取有关该对象的特定数据。此查询需要 60 多秒才能返回。

List<AUser> result = em.createQuery("FROM AUser where company=:companyId")
.setParameter("companyId",company.getId())
.getResultList();

本机查询要快得多。

List<AUser> result = em.createNativeQuery("select a.* FROM AUser a where a.company=:companyId")
.setParameter("companyId",company.getId())
.getResultList();

上述查询不到一秒即可返回。

为什么不一样?

【问题讨论】:

  • 你能将 showSql 设置为 true 并查看 HQL 被翻译成什么 SQL 吗?
  • 我要在这里大胆猜测一下,说你已经在AUser 中映射了一些东西,以便急切地获取。你能发布你的映射吗?此外,请遵循 Kaleb 的建议并发布(800 条中的一些)查询。
  • 正如 Kaleb Brasee 在 hibernate.properties 中建议的那样,设置 hibernate.show_sql=true 以查看 SQL 输出。
  • @ChssPly76,你是对的。我仔细查看了这些查询,并意识到它们不会进入 AUser 表(就像我最初想的那样)。它们是急切地获得的财产的结果。我想我只需要弄清楚如何为不需要这些属性的查询关闭此对象的急切获取。或者,也许有一种方法可以在一个查询中加载所有连接的属性,而不是对每个对象执行一个查询?

标签: java hibernate hql


【解决方案1】:

最初的问题是由于AUser 的属性被急切地获取(HappyEngineer 在评论中确认)。

回答后续问题:

一般来说,最好的方法是将关联映射为惰性:

@ManyToOne(fetch = FetchType.LAZY)
private Company company;

然后您可以使用join fetch 覆盖查询中的提取模式:

select user
  from AUser user left join fetch user.company
 where user.company.id = :companyId

有关详细信息,请参阅 Hibernate 文档中的 Associations and Joins 章节。

【讨论】:

  • 我使用的是 JPA,所以语法有点不同。我不得不使用“LEFT OUTER JOIN”而不是“left join fetch”。不过现在一切正常。
  • 不过,您的问题被标记为“休眠”和“hql”。您可能正在使用 JPA 注释 和 EntityManager,但 HQL 仍然是 HQL。 LEFT OUTER JOIN 等同于 LEFT JOIN,重要的是 FETCH 部分。
【解决方案2】:

这可能是 Hibernate 中的 n+1 选择问题。您应该遵循一些最佳实践来提高您的查询性能。有多个选项,例如延迟加载、获取模式、获取连接等。

http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html n+1 查询问题

问候...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多