我期望仅获得一个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实体列表时发生的。

笔记:


这是Why does this result in non-lazy fetching and N+1 select statements?的后续问题
同样没有解决方案的类似问题在这里:How to lazy load a many-to-many collection in hibernate?

最佳答案

为了解决该问题,您需要使用“批处理大小”和“提取”模式,这里的参考链接将告诉您如何克服N + 1选择问题

希望这会有所帮助

http://www.mkyong.com/hibernate/hibernate-fetching-strategies-examples/

关于java - 延迟加载多对多实体时,为什么会收到N + 1个选择查询,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24984188/

10-10 18:34