【问题标题】:What is the use of the Hibernate @LazyCollection annotationHibernate @LazyCollection 注解有什么用
【发布时间】:2012-10-07 08:40:58
【问题描述】:

我有 2 个实体作为 Parent 和 Child 作为 OneToMany 关系

@Entity
public class Parent {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

private String name;

@OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
@IndexColumn(name = "index", base = 1)
@Cascade(org.hibernate.annotations.CascadeType.ALL)
@LazyCollection(LazyCollectionOption.EXTRA)
private List<Child> childs = new ArrayList<Child>();
// getter and setter

}

那么这里 @LazyCollection(LazyCollectionOption.EXTRA) 有什么用,什么时候会出现,比如对子列表的哪个操作,这将是有益的?

【问题讨论】:

    标签: java performance hibernate orm lazy-loading


    【解决方案1】:

    实际上没有理由使用@LazyCollection

    不需要TRUEFALSE 值,因为可以使用JPA FetchType.LAZYFetchType.EAGER 获得相同的行为。

    EXTRA 值在 JPA 中没有等效值,专为非常大的集合而设计。当您第一次访问 EXTRA 惰性集合时,该集合并未完全加载,任何 JPA 集合通常都是这种情况。

    取而代之的是,使用辅助SELECT 一个一个地获取每个元素。这听起来像是一种优化,但这并不是因为 EXTRA 惰性集合容易出现 N+1 查询问题。

    请注意,这仅适用于有序集合,List(s) 使用 @OrderColumnMap(s) 注释。对于包(例如,不保留任何特定顺序的实体的常规List(s)),@LazyCollection(LazyCollectionOption.EXTRA) 的行为与任何其他LAZY 集合一样(该集合在第一次访问时完全获取)。

    如果你有一个非常大的集合,那么你根本不应该映射它。相反,您应该只映射 @ManyToOne 端,而不是父端集合,您应该使用分页 JPQL 查询。

    JPQL 查询更容易调整,因为您可以应用任何过滤条件,并且可以对结果集进行分页。

    【讨论】:

    • 请问什么是非常大的收藏?
    • 一个非常大的集合是一个需要很长时间才能从数据库中获取的集合。
    • 您在此答案和您的文章中假设集合中的项目将被迭代。情况并非总是如此。我们有几个例子,我们只想在集合中使用.size()。使用@LazyCollection( LazyCollectionOption.EXTRA ),这是一个简单的SELECT COUNT(id) FROM..。没有LazyCollectionOption,操作变成:选择所有匹配的行,映射成对象,然后统计对象的个数。在我运行的简单测试中,与 50,000 个项目集合可能相差 1 或 2 秒。
    • 您假设映射集合是一项职责。只有当它们的大小相当小时,集合才值得映射。对大型集合使用查询,以便您可以对它们进行分页。对于集合大小,只需使用 COUNT 查询。它就像一个魅力。
    • @VladMihalcea 所以你的论点归结为“这个功能很糟糕,因为有人可能会错误地使用它并遇到性能问题”。我不认为这是评估功能有用性的重要标准,并向您建议 Hibernate(以及许多其他库 [以及 Java 和其他语言])中有许多具有相同缺陷的功能(如果您考虑这样的属性是一个缺陷)。
    【解决方案2】:

    EXTRA = .size() 和 .contains() 不会初始化整个集合

    TRUE = 首次访问时初始化整个集合

    FALSE = 急于加载

    【讨论】:

    • .get(0) 会初始化整个集合吗?
    • @LakshayGarg 是的
    • @LakshayGarg,这取决于您使用的选项,EXTRA 不会初始化整个集合,但会对此特定元素执行查询。但是,如果您改为使用附加到此集合的迭代器,它将初始化它 - 就像在流中或在每个循环中一样。 TRUE - 将始终初始化整个集合。
    【解决方案3】:

    给你一个提示,主要是出于性能原因,你可以开始阅读以下链接:

    Second Level Cache

    Hibernate Documentation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 2010-11-24
      • 2017-09-16
      • 2020-03-19
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      相关资源
      最近更新 更多