gpt4 book ai didi

java - 避免子集合元素关联的n+1 eager fetching

转载 作者:搜寻专家 更新时间:2023-11-01 02:29:19 25 4
gpt4 key购买 nike

我有以下类(class):

@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 {
// ...
}

现在我基本上想加载所有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 和 Baz,请使用以下 hql。

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

这应该只产生一个 sql。

此外,如果您不想获取“Baz”,只需将 Bar->Baz 的关联设置为“惰性”即可。

默认情况下,JPA 对“@OneToOne”和“@ManyToOne”关联实现“急切”获取。因此,您必须明确地使其惰性化,如下所示。

@Entity
public class Bar {

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

//...
}

关于java - 避免子集合元素关联的n+1 eager fetching,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13378656/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com