java - 这是一个 N+1 问题吗?我该如何解决它?

标签 java hibernate jpa query-performance

我有一份项目 list 和一份客户 list 。一个项目可以针对一个客户,每个客户可以有多个项目。所以这是一个简单的 1:n 关系,项目是拥有方。

简化到本质

@Entity
public class Project {
  @Id
  long id;

  @ManyToOne(optional = true)
  @JoinColumn(name = "customer", nullable = true, updatable = true)
  Customer customer;
}

@Entity
public class Customer {
  @Id
  long id;
}

当我加载项目列表时,我想同时高效地检索客户。不是这种情况。项目只有一个查询,然后针对遇到的每个不同客户发出单独的查询。

假设我有 100 个项目,分配给 50 个不同的客户。这将导致对项目进行 1 次查询,对客户进行 50 次查询。

这很快就会增加,对于大型项目/客户列表,我们的应用程序变得相当慢。另外,这只是一个例子。我们所有有关系的实体都会受到此行为的影响。

我已经按照建议在 customers 字段上尝试了 @Fetch(FetchMode.JOIN) here但它什么也不做,并且 FetchMode.SUBQUERY 根据 Hibernate 不适用:

org.hibernate.AnnotationException: Use of FetchMode.SUBSELECT not allowed on ToOne associations

如何解决这个问题?

最佳答案

是的,这是 n+1 选择问题的常规示例。

我在大多数情况下使用的方法是使关联变得惰性并定义 batch size .

或者,您可以使用带有 [left] join fetch 的 JPQL 查询直接从查询结果集初始化关联:

select p from Project p left join fetch p.customer

关于java - 这是一个 N+1 问题吗?我该如何解决它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36569318/

相关文章:

java - 使用 Spring Boot 和 Spring Data JPA 的 CriteriaQuery 中出现空指针异常

java - 我可以在 JVM 在 OOM 上调用的脚本中使用 "kill %p"

java - Hibernate 和 Spring - 不会自动创建数据库表

hibernate - 当我有@ManyToMany 时如何设置外键名称

java - Spring 数据保存与 saveAll 性能

jpa - 如何添加不区分大小写的 JPA 唯一约束?

java - 如何从mysql表中检索字符值?

java - SpecJMS 和 HornetQ

java - 如果我使用 myBatis 从几乎相同的表中提取时如何删除大量重复代码

mysql - 为什么我的 mysql 查询在 JPA 中不起作用?