Mor*_*sen 4 java hibernate jpa hql
我有以下课程:
@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 {
// ...
}
Run Code Online (Sandbox Code Playgroud)
现在我基本上想要加载所有Base但是在适用的时候加载吧,所以我使用以下查询:
SELECT b FROM Base b LEFT JOIN FETCH b.bars
Run Code Online (Sandbox Code Playgroud)
虽然这有效,但似乎为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 ...
Run Code Online (Sandbox Code Playgroud)
是否有可能告诉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]
Run Code Online (Sandbox Code Playgroud)
我也尝试过使用IN(b.bars) bars,虽然这允许我引用子集合,但它似乎并没有急切地加载我目标的条形集合.
解释为什么会发生这种情况也很好,因为我似乎无法弄明白.
如果你想用out(n + 1)选择检索Bar和Baz,请使用以下hql.
SELECT b FROM Base b LEFT JOIN FETCH b.bars bar LEFT JOIN FETCH bar.baz
Run Code Online (Sandbox Code Playgroud)
这应该只导致一个sql.
此外,如果您不想获取'Baz',只需从Bar-> Baz'懒惰'进行关联.
默认情况下,JPA强制'eager'获取'@OneToOne'和'@ManyToOne'关联.所以,你必须明确地使它变得懒惰,如下所示.
@Entity
public class Bar {
@OneToOne
@JoinColumn(name = "baz_id", nullable = false, fetch=FetchType.Lazy)
private Baz baz;
//...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6218 次 |
| 最近记录: |