当前位置: 首页 > 面试题库 >

Hibernate可以用于对性能敏感的应用程序吗?

狄元魁
2023-03-14
问题内容

我在检索与其他对象有许多关系的对象的多个实例时遇到性能问题。我正在将Spring和Hibernate的JPA实现与MySQL配合使用。问题是执行JPA查询时,Hibernate不会自动联接到其他表。这将导致n * r + 1个SQL查询,其中n是要检索的对象数,r是关系数。

例如,某人住在某个地址,有很多爱好,并且访问过许多国家:

@Entity
public class Person {
    @Id public Integer personId;    
    public String name;    
    @ManyToOne public Address address;    
    @ManyToMany public Set<Hobby> hobbies;    
    @ManyToMany public Set<Country> countriesVisited;
}

当我执行JPA查询以获取所有名为Bob的个人时,数据库中有100个Bobs:

SELECT p FROM Person p WHERE p.name='Bob'

Hibernate将此转换为301 SQL查询:

SELECT ... FROM Person WHERE name='Bob'
SELECT ... FROM Address WHERE personId=1
SELECT ... FROM Address WHERE personId=2
...
SELECT ... FROM Hobby WHERE personId=1
SELECT ... FROM Hobby WHERE personId=2
...
SELECT ... FROM Country WHERE personId=1
SELECT ... FROM Country WHERE personId=2
...

根据Hibernate
FAQ(此处和此处),解决方案是在查询中指定LEFT
JOIN或LEFT OUTER
JOIN(用于多对多)。所以现在我的查询看起来像:

SELECT p, a, h, c FROM Person p
LEFT JOIN p.address a LEFT OUTER JOIN p.hobbies h LEFT OUTER JOIN p.countriesVisited c
WHERE p.name = 'Bob'

这可以工作,但是如果有多个LEFT OUTER JOIN,则似乎存在错误,在这种情况下,Hibernate错误地寻找了不存在的列:

could not read column value from result set: personId69_2_; Column 'personId69_2_' not found.

该错误行为似乎由Hibernate
Core错误HHH-3636解决。不幸的是,该修复程序不是任何已发布的Hibernate
JAR的一部分。我已经针对快照html" target="_blank">构建运行了我的应用程序,但是错误行为仍然存在。我还从存储库中的最新代码构建了自己的Hibernate Core
JAR,并且该错误行为仍然存在。因此,也许HHH-3636无法解决此问题。

Hibernate的性能限制非常令人沮丧。如果我查询1000个对象,则会对数据库进行1000 * r +
1个SQL查询。就我而言,我有8个关系,因此我得到8001个SQL查询,这导致了可怕的性能。Hibernate的官方解决方案是保留所有关系。但是由于错误的行为,对于多于许多的关系这是不可能的。因此,由于多对多关系,我对多对一关系和n * r + 1查询使用左联接。我计划将“ LEFT OUTER
JOIN”问题作为Hibernate错误提交,但与此同时,我的客户需要一个性能合理的应用程序。我目前使用批处理提取(BatchSize)的组合,ehcache和自定义内存缓存,但性能仍然很差(将30个秒内的5000个对象检索到8秒的性能得到了改善)。最重要的是,有太多的SQL查询正在访问数据库。

因此,我的问题是,可以在表之间具有多个关系的对性能敏感的应用程序中使用Hibernate吗?我很想听听Hibernate如何成功使用地址性能。我应该手写SQL(这在某种程度上违背了使用Hibernate的目的)吗?我应该对数据库架构进行非规范化以减少联接表的数量吗?如果我需要快速的查询性能,是否应该不使用Hibernate?有更快的东西吗?


问题答案:

如果您阅读了链接到的所有常见问题解答,请参阅我对其他问题的回答:

遵循最佳做法指南!确保在Hibernate2中所有映射和映射都指定lazy =“ true”(这是Hibernate3中的新默认设置)。使用HQL
LEFT JOIN FETCH指定在初始SQL SELECT中需要检索的关联。

避免n + 1选择问题的第二种方法是在Hibernate3中使用 fetch =“ subselect”

如果仍然不确定,请参考Hibernate文档和Hibernate in Action。

请参阅有关提高性能的提示。如果对联接不小心,则会导致笛卡尔积问题。



 类似资料:
  • 我们是否可以使用 MIP SDK 将敏感度标签应用于 SharePoint Online 文件。如果是,请提供参考/示例代码以应用敏感度标签。

  • 问题内容: 我怀疑对于Web应用程序(JSP,Servlet,Hibernate,MySQL)是否安全,在Web应用程序中“不同的用户”可以一次获得数千次访问。 我担心的原因如下。 想象一下,我有一个针对学校学生的Web应用程序。他们有自己的个人资料,并将维护自己的学生课程,成绩等。现在,肯定有1个以上的用户将始终使用自己的个人资料在线。这意味着,如果用户对其数学标记进行了编辑,则将在用户的个人资

  • 我见过一些APM,它只测量运行在WAS上的网络应用程序。 Elastic APM能否衡量纯Java应用程序等其他应用程序的性能? 如果没有,我可以使用吗https://www.elastic.co/guide/en/apm/agent/java/1.x/public-api.html(公共API),以便它可以测量非web应用程序的性能? 我将感谢你的建议。干杯

  • 任务是编写一个代码,将敏感度标签应用于 SharePoint Online 文档库中的文档,而无需下载该文件。 到目前为止,我已经探索了以下API: SharePoint REST API v1:可用于设置保留标签,但不能设置敏感度标签。 Microsoft Graph REST API:在此 API 中找不到任何用于设置任何标签的公共方法。所有与标签相关的属性似乎都是只读的。 Microsoft

  • 相信大家已经发现,Qt 应用程序在每一个所支持的平台上都可以看起来像原生的本地程 序一样。Qt 是通过模拟各个平台的观感来实现这一点的 ,而不是使用特定的平台或者工具包 的窗口部件集。图 9-1 显示了在不同平台下的 Qt 组件中的 ComboBox 的观感。 9.1.1 应用程序的风格 图 9-1 窗口部件在不同平台上的观感 每个应用程序都有自己的样式(Style)。运行于 KDE 下的 Qt/

  • Spring Boot文档说我们可以在application.properties文件中设置属性。 但我找不到列出可设置的可用属性的文档。 在哪里可以找到这样的文档? 例如,我想为嵌入式Servlet设置documentRoot。 我发现setDocumentRoot()方法是在AbstractembedDedServletContainerFactory.java中实现的。 但我不知道何时何地调