我面临 2 个问题:N + 1 查询和内存不足 (OOM)。
我通过分页和延迟加载解决了OOM:
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Set<Employee> employees;
但是当我使用延迟加载时,发生了N+1次查询。所以我尝试使用 EntityGraph 作为 https://www.baeldung.com/spring-data-jpa-named-entity-graphs 。但根据我的研究和本地测试,EntityGraph
总是对 NamedAttributeNode
字段 - 关联字段进行急切加载,我希望延迟加载 - 首先不要加载所有数据:
@Entity
@Table(name = "department")
@NamedEntityGraph(name = "Department",
attributeNodes = {
@NamedAttributeNode("employees")
}
)
public class Department implements Serializable {
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "department_id")
private Set<Employee> employees;
}
那么有什么办法可以同时获得它们吗?使用EntityGraph避免N+1和延迟加载以避免OOM?
更新:
EntityGraph
可以与 Pageable 有效地配合使用吗?我的意思是不要在 JOIN 查询中加载所有数据。
最佳答案
使用 EntityGraph
,所有 NamedAttributeNode
关联都将加载到带有 Join
子句的 1 个查询中。启用sql日志查看hibernate在不同场景下加载实体有多少查询
logging.level.org.hibernate.SQL=DEBUG
您将看到,在不使用 EntityGraph
的情况下使用 @OneToMany(fetch = FetchType.EAGER)
会在单独的 select
查询中加载员工(N + 1),但使用 EntityGraph
它只执行 1 select ... join
另外,不要忘记在存储库中指定实体图名称,例如:
@EntityGraph(value = "Department")
List<Department> findAll();
更新: Spring DATA 分页在数据库端不起作用。它将获取所有数据,然后在内存中进行过滤。这就是它的工作原理。有一些解决方法,请检查此链接:
VladMihalcea Blog The best way to fix the Hibernate HHH000104
对我来说,解决方案可以是创建自定义存储库并使用 EntityManager
手动构建查询。
关于java - 使用 Spring data JPA EntityGraph 和 NamedAttributeNode 字段的 LAZY 加载模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60109680/