当前位置: 首页 > 面试题库 >

避免n + 1渴望获取子集合元素关联

姜德容
2023-03-14
问题内容

我有以下课程:

@Entity
@Table(name = "base")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING)
@ForceDiscriminator
public class Base {
    // ...
}

@Entity
@DiscriminatorValue("foo")
public class Foo extends Base {
    @OneToMany( mappedBy = "foo", cascade=CascadeType.ALL )
    private List<Bar> bars = new ArrayList<Bar>();

    // ...
}

@Entity
public class Bar {
    @ManyToOne (optional = false)
    @JoinColumn(name = "foo_id" )
    private Foo foo;

    @OneToOne
    @JoinColumn(name = "baz_id", nullable = false)
    private Baz baz;

    //...
}

@Entity
public class Baz {
    // ...
}

现在,我基本上想加载all Base,但在适用时渴望加载条,所以我使用以下查询:

SELECT b FROM Base b LEFT JOIN FETCH b.bars

在这种情况下,似乎为Bar实体产生了SELECT N + 1问题:

Hibernate: /* SELECT b FROM Base b LEFT JOIN FETCH b.bars */ SELECT ...
Hibernate: /* load com.company.domain.Baz */ SELECT ...
Hibernate: /* load com.company.domain.Baz */ SELECT ...

是否可以告诉hibernate急切地为子集合中的每个元素加载一个关联,而无需诉诸N + 1 SELECT?

我尝试了以下查询,但由于它是一个集合,因此显然无法正常工作:

SELECT b FROM Base b LEFT JOIN FETCH b.bars LEFT JOIN FETCH b.bars.baz
//Results in: illegal attempt to dereference collection [Foo.id.bars] with element property reference [baz]

我也尝试使用IN(b.bars) bars,虽然这使我可以引用子集合,但似乎并没有急于加载bars集合,这是我的目标。

解释为什么会发生这种情况也很好,因为我似乎无法弄清楚。


问题答案:

如果您想不选择(n + 1)来检索Bar and Baz,请使用以下hql。

SELECT b FROM Base b LEFT JOIN FETCH b.bars bar LEFT JOIN FETCH bar.baz

这应该只导致一个sql。

另外,如果您不想获取’Baz’,则只需从Bar-> Baz’lazy’中进行关联即可。

默认情况下,JPA对“ @OneToOne”和“ @ManyToOne”关联强制执行“紧急”获取。因此,您必须显式使其变得懒惰,如下所示。

@Entity
public class Bar {

    @OneToOne
    @JoinColumn(name = "baz_id", nullable = false, fetch=FetchType.Lazy)
    private Baz baz;

    //...
}


 类似资料:
  • 问题内容: 假设项目和出价是实体:一个项目有很多出价。它们在 Hibernate 中以典型的父/子关系映射: 在执行此查询后尝试访问每个项目的出价时,如何避免n + 1个选择? 请注意, 我需要 急切 的竞标价格,但 对收款 要有 进一步的限制 (b.amount> 100) 我尝试了以下失败: 问题答案: 这说明了为什么对fetch-joined集合添加限制会导致集合未初始化( 请注意 ,没有限

  • 我有以下课程: 现在我基本上想加载所有的,但在适用时渴望加载条,所以我使用以下查询: 虽然这是可行的,但它似乎为Bar实体生成了一个SELECT N 1问题: 有没有可能告诉hibernate急切地为子集合中的每个元素加载关联,而不使用N 1 SELECTs? 我尝试了以下查询的思路,这显然不起作用,因为它是一个集合: 我还尝试在(b.bar)bar中使用

  • 问题内容: 我有四个表: 和类似的实体结构: 我需要一个查询将返回所有与它在表和孩子初始化。该是预先抓取,但孩子们是懒牵强。 我知道如何编写查询,将查询表的直接子级并相应地对其进行初始化。但是,我不知道如何获取从顶层表急切获取的表的子级。 我已经尝试过类似的东西: 但是,这总是给我一个错误,即所有者不是SELECT的一部分。 任何帮助是极大的赞赏。 问题答案: Hibernate参考 我们可能需要

  • 这是一个算法问题。如果我错过了Python中任何有帮助的现有函数,请大喊一声。 给定一组元素的,我们可以在Python中使用函数来找到所有唯一的k元素子集。让我们调用包含所有这些子集的集合。请注意,每个这样的子集都有不同的元素。 问题是两步走。首先,给定这些k-不同元素子集,我想组合(其中的一些),这样(组合只是一些子集的超集): > 构图中任意两个子集之间的交集为空 构图中所有子集的并集给出的正

  • 本文向大家介绍Python获取子列表元素直到N,包括了Python获取子列表元素直到N的使用技巧和注意事项,需要的朋友参考一下 在本教程中,我们将编写一个程序,该程序返回一个子列表元素,直到列表中的第n个子列表。假设我们有以下列表和5个子列表。 [['Python','Java'],['C','Pascal'],['Javascript','PHP'],['C#','C ++'],['React'

  • 问题内容: 我有一个我认为应该很普遍的问题,但找不到答案。 我有2个对象:组和用户。我的课程如下所示: 现在,当我尝试从数据库中获取用户时,它带来了所有组,所有组都带来了所有用户,依此类推。最后,我遇到了stackoverflow异常。 如何解决此问题,并且仍然具有双向关联以及到达列表中对象的能力? 问题答案: 如果使用属性(无论如何都应使用)将双向关联的一侧设为关联的 拥有 侧,是否会遇到相同的