[英]Why do I get N+1 select queries when lazy loading many-to-many entities
我期望仅获得一个sql查询,但遇到N + 1选择陷阱。 我真的不明白为什么。 这是详细的问题:
我有一个实体“ PlayerRef”:
@Entity
@Table(name = "player_ref")
public class PlayerRef {
//constructor etc...
@OptimisticLock(excluded = true)
@LazyCollection(LazyCollectionOption.TRUE)
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "playerRefs")
public Set<Player> getPlayers() {
return players;
}
}
和一个班级球员:
@Entity
@Table(name = "player")
public class Player {
//constructor etc...
@OptimisticLock(excluded = true)
@LazyCollection(LazyCollectionOption.TRUE)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name="cr_player_ref_player",
joinColumns = {
@JoinColumn(name="player_id", unique = true)
}
,inverseJoinColumns = {
@JoinColumn(name="player_ref_id")
}
)
private Set<PlayerRef> getPlayerRefs() {
return this.playerRefs;
}
}
现在,在我的程序中,我使用以下HQL查询来获取所有playerRef实体:
Query playerRefQ = session.createQuery("select playerRef from PlayerRef playerRef ")
.setReadOnly(true);
playerRefQ.setParameter("sport", sport);
@SuppressWarnings("unchecked")
List<PlayerRef> allPlayerRefs = playerRefQ.list();
这将导致N + 1个Select语句:
1)
select
playerref0_.id as id1_21_0_,
...
from
player_ref playerref0_
N次)
select
players0_.player_ref_id as player_r2_21_0_,
players0_.player_id as player_i1_34_0_,
player1_.id as id1_19_1_,
...
from
cr_player_ref_player players0_
inner join
betdata.player player1_
on players0_.player_id=player1_.id
where
players0_.player_ref_id=?
(再次)这是非常出乎意料的,因为我认为该集合是延迟加载的,并且每个playerRef的播放器集都应该是休眠代理。
谁知道我真的只能加载playerRef实体,而又不加载关联的玩家吗? 对于我的用例,我需要所有playerRefs,但不需要关联的players。
在我的较早问题中,有人建议,可以某种方式引用引用关联实体的方式重写playerRef或Player的toString()方法。 不是这种情况。 N + 1查询是在访问所有playerRef实体列表时发生的。
笔记:
这是为什么会导致非延迟获取和N + 1选择语句的后续问题?
同样没有解决方案的类似问题在这里: 如何在休眠状态下延迟加载多对多集合?
为了解决该问题,您需要使用“批处理大小”和“提取”模式,这里的参考链接将告诉您如何克服N + 1选择问题
希望这会有所帮助
http://www.mkyong.com/hibernate/hibernate-fetching-strategies-examples/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.