如何高效为feed列表设置用户点赞标记,避免额外N次数据库查询
优化方案1:单SQL关联查询一次性拉取全量数据
你可以在原有的Feed关联查询基础上,增加对当前用户点赞记录的左关联,直接通过判断点赞记录是否存在返回标记,全程只需1次数据库查询。
适配JPA的JPQL示例:
SELECT DISTINCT f, CASE WHEN fl.id IS NOT NULL THEN true ELSE false END AS isLikedByUser FROM Feed f LEFT JOIN FETCH f.feedMedia m LEFT JOIN FeedLikes fl ON fl.feedId = f.feedId AND fl.userId = :currentLoginUserId -- 这里加你的原有过滤、排序、分页条件
查询返回结果可以通过JPA的构造器投影映射到自定义的DTO对象,同时包含Feed、关联的FeedMedia列表、以及isLikedByUser标记,无需额外查库。
优化方案2:批量查询+内存匹配(改造成本最低)
如果你不想改动原有复杂的Feed查询逻辑,可以用2次查询完成所有逻辑,性能远优于原有的N+1查询:
- 执行原有Feed列表查询,拿到当前分页的所有Feed记录,收集所有feedId到
List<Integer> feedIdList集合中 - 执行1次批量点赞查询,拿到当前用户点赞过的所有当前页feedId:
// 对应JPA查询方法 @Query("select fl.feedId from FeedLikes fl where fl.userId = :userId and fl.feedId in :feedIdList") List<Integer> listLikedFeedIdByUserIdAndFeedIds(@Param("userId") Integer userId, @Param("feedIdList") List<Integer> feedIdList);
- 将查询到的点赞feedId存入
HashSet<Integer> likedFeedIdSet,遍历Feed列表时直接判断likedFeedIdSet.contains(feed.getFeedId())即可设置isLikedByUser标记。
两种方案选型建议
- 优先选方案1,单查询性能最优,适合分页逻辑不复杂的场景
- 原有Feed查询逻辑复杂(多条件过滤、多表关联)的场景选方案2,改造成本极低,不易出错
内容的提问来源于stack exchange,提问作者Meet Shah
相关产品推荐
相关产品推荐

