- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有以下类(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/
我以前使用过像 Netbeans 和 eclipse 这样的 IDE。 我在 friend 的电脑上下载了“Visual Studio Express 2013 for windows desktop
我正在尝试弄清楚如何在 GBA 大小的 EZ Flash 3 合 1 卡中对 PSRAM 进行编程。基本上重复 GBA Exploader 和其他程序所做的事情。 如果我选择一个 block 并对其进
Filter1=re.findall(r'',PageSource) Filter2=re.findall(r'',PageSource) Filter3=re.findall(r'(.*?).*?'
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许在 Stack Overflow 上提出有关通用计算硬件和软件的问题。您可以编辑问题,使其成为
我是一名优秀的程序员,十分优秀!