【问题标题】:Using Spring data JPA EntityGraph with LAZY load mode for NamedAttributeNode field将 Spring 数据 JPA EntityGraph 与 NamedAttributeNode 字段的 LAZY 加载模式一起使用
【发布时间】:2020-05-23 08:49:36
【问题描述】:

我面临 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 查询中加载所有数据。

【问题讨论】:

    标签: java spring-boot spring-data-jpa out-of-memory lazy-loading


    【解决方案1】:

    使用EntityGraph,您的所有NamedAttributeNode 关联都将在带有Join 子句的1 个查询中加载。开启sql log查看hibernate在不同场景下加载实体做了多少查询

    logging.level.org.hibernate.SQL=DEBUG
    

    您会看到,使用 @OneToMany(fetch = FetchType.EAGER) 而不使用 EntityGraph 它会在单独的 select 查询 (N + 1) 中加载员工,但使用 EntityGraph 它只会执行 1 个 select ... join

    另外不要忘记在存储库中指定实体图名称,例如:

    @EntityGraph(value = "Department")
    List<Department> findAll();
    

    更新: Spring DATA 分页在数据库端不起作用。它将获取所有数据,然后在内存中进行过滤。这就是它的工作原理。有一些解决方法,请查看以下链接:

    How can I avoid the Warning "firstResult/maxResults specified with collection fetch; applying in memory!" when using Hibernate?

    Avoiding "HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!" using Spring Data

    VladMihalcea Blog The best way to fix the Hibernate HHH000104

    就我而言,解决方案可能是创建自定义存储库并使用EntityManager 手动构造查询。

    【讨论】:

    • "您会看到,在没有 EntityGraph 的情况下使用 @OneToMany(fetch = FetchType.EAGER) 会在单独的选择查询 (N + 1) 中加载员工,但使用 EntityGraph 它只执行 1 次选择...加入" -> 这就是我上面提到的:它会加载员工 EAGERLY 但我希望它是 LAZY
    • @ThachHuynh 好的,那你为什么需要EntityGraph?只是不要为懒惰的员工使用@NamedAttributeNode。在这种情况下,员工根本不会被加载。
    • 我使用EntityGraph是因为它可以避免N+1选择问题。
    • 还有其他方法吗?
    • @ThachHuynh 我已经更新了答案。可能你会发现那里很有用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 2014-03-10
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    相关资源
    最近更新 更多