[英]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.