【问题标题】:Fetch.Lazy when you retrieve a List and Fetch.Eager when you return one EntityFetch.Lazy 当你检索一个 List 和 Fetch.Eager 当你返回一个实体
【发布时间】:2020-04-18 07:53:02
【问题描述】:

我一直认为在 Spring/Hibernate 中处理这个问题的最佳方法是什么。假设我们有一个像 House 这样的实体:

public class House {
    Long id;
    String name;
    String address;
    List<Person> people;
}

Person 是另一个实体。现在,如果我们想要显示存储的每个房屋的列表,我们只需要一些详细信息、id、名称和地址,我们不希望获取整个数据,因为我们没有显示列表中的人。 然而,当我们进入详细视图时,我们也有兴趣向人们展示。

在需要时获取人员的最佳方法是什么,同时处理 LazyInitializationException?

【问题讨论】:

    标签: java spring hibernate jpa spring-data-jpa


    【解决方案1】:

    有多种选择。我只是突出显示我使用的那个:

    加入获取

    如果您需要热切加载的人,您可以创建如下查询:

    select h from House h fetch join people p
    

    如果您认为这会产生很多查询,请选择实体图。

    实体图

    定义:

    @Entity
    @NamedEntityGraph(name = "graph.House.people", 
          attributeNodes = @NamedAttributeNode("people"))
    public class House {
    

    与 Spring Data JPA 一起使用:

    @EntityGraph(value = "graph.House.people", type = EntityGraphType.LOAD)
    List<House> findById(Long id);
    

    但还有更多。请阅读:https://thoughts-on-java.org/5-ways-to-initialize-lazy-relations-and-when-to-use-them/

    【讨论】:

    • 我看到您的解决方案的唯一缺点是,当我想要获取所有内容时,我需要编写更多查询。最好在 jpa 查询名称中使用一些快捷方式,就像在 findById() 中一样,例如 findByIdFetchPeople。
    • 我添加了一个带有实体图的解决方案,可以减少查询量。
    【解决方案2】:

    您可以使用存储库中的实体图。只需使用 @EntityGraph 在您的方法上定义一个临时实体图。

    @EntityGraph(attributePaths = {"people"})
    List<House> findAll();
    

    在这里,您可以将要获取的属性定义为attributePaths。 当你想向人们展示时调用它,否则调用findAll()

    您还可以对people 使用惰性获取,只要您想要people,只需调用它的getter,JPA 将在另一个查询中自动获取people

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-21
      • 2020-12-14
      • 1970-01-01
      • 2021-03-17
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多