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

标签 java hibernate jpa hql

我有以下类(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/

相关文章:

java - 是否可以用 Java Swing 程序替换鼠标?

java - 我正在恢复一个数据库,我需要在我的 Java 应用程序中锁定它的任何 Activity

java - Hibernate JPA 父子映射

java - JPQL多对多选择查询

java - 如何解决这个异常: "X references an unknown entity: Y"?

java - 替代 SocketUtils.findAvailableTcpPort()?

java - HttpServletResponse编码问题

java - 我已经使用了 SelectBeforeUpdate 但每次我坚持一个分离的对象而不进行任何更改时, hibernate 都会使用带有 null 的列值进行保存

java - EntityManagerFactory 中未指定 PersistenceProvider,并且选择的 PersistenceUnitInfo 未指定基于注释的配置

java - Hibernate:将父实体映射到子实体,并有 2 个对子实体中一列的引用?