【发布时间】:2022-12-10 16:32:27
【问题描述】:
我有一个像下面代码这样的实体,其中每个短语我都可以有多种不同语言的翻译。
问题是,当我获取翻译时,Hibernate 会为每个短语查询数据库。
因此,如果我有 1000 个翻译,Hibernate 将自动对翻译进行 1 次查询,对短语表进行 1000 次查询。
但与 JOIN 和单个查询相比,这是非常慢的: “SELECT * FROM ad_translations a JOIN ad_phrase ap ON (ap.id = a.id_ad_phrase)”
在这种情况下有哪些选择?我应该使用 Native SQL 还是有更好的方法?
@Entity
@Table(name="ad_translations")
public class Translations implements Serializable {
...
@ManyToOne
@JoinColumn(name="id_ad_phrase")
private Phrase idAdPhrase;
@ManyToOne
@JoinColumn(name="id_ad_lang")
private Lang idAdLang;
...
}
更新: 我在这里阅读了 3 种可能的解决方案https://hackernoon.com/3-ways-to-deal-with-hibernate-n1-problem 但一切似乎都不完美:
- 第一个解决方案是 NativeSQL,从性能的角度来看,它一定是正确的,但是采用这种方式,我在获取数据时需要编写大量代码,因为我必须手动为 Lang 和短语并根据查询结果填充它们。
- 第二个解决方案(@BatchSize)涉及太多查询
- 第三个解决方案(@Fetch(FetchMode.SUBSELECT))在性能方面明显不如第一个
FetchType.Lazy 将无济于事,因为我在 REST 应用程序中使用此实体,所有数据都将在序列化时获取。
我不确定投影如何影响 N+1 问题,似乎它们只有助于使用自定义列数进行选择,但查询数保持不变。
我不知道为什么 Hibernate 没有自动 JOIN 选项,所以我们可以使用第一个解决方案,只需编写很少的代码。
我将选择本机 SQL 选项。
【问题讨论】:
-
这被称为N+1 problem。有几种方法可以提高性能。 “正确”的取决于具体的用例。我建议研究该主题,然后决定哪种方法最适合给定的用例。
标签: java spring spring-boot hibernate