fix(posts): Copilot CR 6 条健壮性修复(N+1/404/409/slug)#36
Merged
Conversation
- N+1:findFeedWithAuthor 改 JOIN 一次取回作者字段,消除 service 层逐行 findById - update() slug 规范化:前端传入的 slug 统一经 sanitizeSlug(),与 create 行为一致 - requirePost() 改抛 ResourceNotFoundException(404),GlobalExceptionHandler 单独处理 - create() / update() 捕获 DuplicateKeyException 返回 409(参考 SharedLinkController) - repository.update() 返回 int(affected rows);0 行时 service 抛 404 而非 IllegalStateException Co-authored-by: copilot-pull-request-reviewer[bot] <198982749+copilot-pull-request-reviewer[bot]@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
该 PR 针对 posts 模块在 #35 合并后提出的健壮性问题做集中修复,目标是改进 feed 查询性能、规范 slug 处理,并将若干异常场景从 400/500 调整为更合理的 404/409 响应语义。
Changes:
listFeed去除 service 层 N+1 查询,改为 repository JOIN 一次取回作者字段update统一对传入 slug 做sanitizeSlug(),并用受影响行数判断并发删除场景返回 404- 新增
ResourceNotFoundException并在GlobalExceptionHandler中映射为 404;create/update捕获DuplicateKeyException返回 409
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/main/java/com/involutionhell/backend/posts/service/PostService.java | update slug 规范化、并发删除 404、feed 改走 JOIN 查询 |
| src/main/java/com/involutionhell/backend/posts/repository/PostRepository.java | repository 接口调整:feed 改为返回带作者信息的结果;update 返回受影响行数 |
| src/main/java/com/involutionhell/backend/posts/repository/JdbcPostRepository.java | 实现 JOIN 查询的 feed 方法;update 改返回 int |
| src/main/java/com/involutionhell/backend/posts/controller/PostController.java | create/update 捕获重复键异常并返回 409 |
| src/main/java/com/involutionhell/backend/common/error/ResourceNotFoundException.java | 新增 404 语义业务异常类型 |
| src/main/java/com/involutionhell/backend/common/error/GlobalExceptionHandler.java | 新增 ResourceNotFoundException → 404 映射 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+119
to
+133
| public List<PostSummaryView> findFeedWithAuthor(int limit, int offset) { | ||
| // JOIN user_accounts 一次拿回作者字段,消除 service 层 N+1 查询 | ||
| String sql = "SELECT p.id, p.author_id, p.slug, p.title, p.description, p.tags, " | ||
| + "p.cover_url, p.visibility, p.status, p.promoted_pr_url, " | ||
| + "p.view_count, p.created_at, p.updated_at, " | ||
| + "u.username AS author_username, " | ||
| + "u.display_name AS author_display_name, " | ||
| + "u.avatar_url AS author_avatar_url " | ||
| + "FROM posts p " | ||
| + "LEFT JOIN user_accounts u ON u.id = p.author_id " | ||
| + "WHERE p.status = ? AND p.visibility = ? " | ||
| + "ORDER BY p.created_at DESC LIMIT ? OFFSET ?"; | ||
| return jdbc.query(sql, (rs, rowNum) -> { | ||
| Post p = rowMapper.mapRow(rs, rowNum); | ||
| String username = rs.getString("author_username"); |
Comment on lines
29
to
35
| /** | ||
| * 公开 feed 列表:status=PUBLISHED + visibility=PUBLIC,按 created_at DESC 分页。 | ||
| * JOIN user_accounts 一次取回作者信息,避免 service 层 N+1 查询。 | ||
| * limit 上限由 Service 层限定,避免超大 offset 拖垮 DB。 | ||
| */ | ||
| List<Post> findFeed(int limit, int offset); | ||
| List<PostSummaryView> findFeedWithAuthor(int limit, int offset); | ||
|
|
Comment on lines
+56
to
+59
| } catch (DuplicateKeyException e) { | ||
| return ResponseEntity.status(HttpStatus.CONFLICT) | ||
| .body(new ApiResponse<>(false, "slug 已被占用,请修改文件名后重试", null)); | ||
| } |
Comment on lines
+74
to
+77
| } catch (DuplicateKeyException e) { | ||
| return ResponseEntity.status(HttpStatus.CONFLICT) | ||
| .body(new ApiResponse<>(false, "slug 已被占用,请修改文件名后重试", null)); | ||
| } |
Comment on lines
+97
to
+101
| @ExceptionHandler(ResourceNotFoundException.class) | ||
| public ResponseEntity<ApiResponse<Void>> handleResourceNotFound(ResourceNotFoundException e) { | ||
| return ResponseEntity.status(HttpStatus.NOT_FOUND) | ||
| .body(ApiResponse.fail(e.getMessage())); | ||
| } |
longsizhuo
added a commit
that referenced
this pull request
May 24, 2026
#36 的 JOIN SQL 只 SELECT 了部分列,rowMapper 读 content_md 时 PSQLException: column not found。改 SELECT p.* 保留全列, author_* 别名列追加在后,rowMapper 正常工作。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
背景
针对 #35 合并后 Copilot 提出的 6 条 CR,逐条修复。
修复清单
listFeedN+1:每篇 post 单独查user_accountsfindFeedWithAuthor改用LEFT JOIN user_accounts一次取回作者字段update()slug 未 sanitizesanitizeSlug()(小写/连字符/长度限制),与create行为一致requirePost()抛IllegalArgumentException→ 400ResourceNotFoundException,GlobalExceptionHandler 映射为 404create()未 catchDuplicateKeyException→ 500update()同上update()并发删除后IllegalStateException→ 400repository.update返回intaffected rows;0 行抛 404验证
./mvnw -q -DskipTests package编译通过,无输出。Co-authored-by: copilot-pull-request-reviewer[bot] <198982749+copilot-pull-request-reviewer[bot]@users.noreply.github.com>