You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么使用@Fetch(FetchMode.SUBSELECT)时执行2条SQL而非1条?

解答

@Fetch(FetchMode.SUBSELECT) 本身的设计就是产生2条SQL,你遇到的是正常现象,并非代码或配置错误。

核心原因说明

  • SUBSELECT的执行逻辑分为两步:
    1. 执行主查询:调用findAll()方法时,Hibernate仅执行第一条SQL查询所有Restaurant实体数据,此时关联的votes是懒加载代理对象,未加载真实数据。
    2. 触发关联查询:在getRestaurantVoteCount()方法中调用restaurant.getVotes()时触发懒加载,Hibernate会执行第二条SQL,将第一次查询所有Restaurant的id作为in条件,一次性查出所有餐厅对应的所有Vote数据,直接避免了默认懒加载的N+1问题(即每访问一个餐厅的votes就生成一条SQL的情况)。
  • 你误以为的「1次SQL查询」是FetchMode.JOIN的效果,但FetchMode.JOIN仅对findById()这类单实体查询生效,对findAll()批量查询默认失效。如果要实现1次SQL拉取所有数据,可自定义JPQL使用LEFT JOIN FETCH:
    @Query("SELECT DISTINCT r FROM Restaurant r LEFT JOIN FETCH r.votes")
    List<Restaurant> findAllWithVotes();
    
    注意该写法在单餐厅关联Vote数量较多时,会产生笛卡尔积重复数据,因此需要加DISTINCT去重。

优化建议

你当前的逻辑仅需要统计当日投票数,把全量历史Vote加载到内存再过滤非常浪费性能,可直接通过聚合查询在数据库层完成统计,或者使用@Formula注解直接映射当日投票数字段,无需加载全量Vote数据。

内容的提问来源于stack exchange,提问作者user15599360

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 20:39:02