✨ Feat: Match 도메인 조회 API 추가 (참가자 목록 / 구장 기반 매칭)#72
Conversation
GET /api/matches/{matchId}/participants
JOINED 상태 참가자만 반환 (N+1 방지 fetch join)
GET /api/matches?facilityId={facilityId}
OPEN/FULL 상태이며 시작 전인 매칭만 반환
Walkthrough매칭 도메인에 두 가지 새로운 API 엔드포인트를 추가했습니다: 특정 매치의 참가자 목록을 조회하는 엔드포인트와 시설별 진행 예정인 매칭 목록을 조회하는 엔드포인트입니다. 이를 위해 컨트롤러, 서비스, 리포지토리 계층에 대응하는 메서드들을 추가했습니다. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/main/java/com/be/sportizebe/domain/match/repository/MatchParticipantRepository.java`:
- Around line 35-37: The query in
MatchParticipantRepository.findAllByMatchRoomIdAndStatusFetch lacks an ORDER BY
so result order can vary; update the JPQL to include a deterministic ordering
(e.g., append "ORDER BY mp.createdAt ASC" or "ORDER BY mp.id ASC" depending on
which field represents join order) so participants are consistently returned in
the intended sequence when selecting MatchParticipant JOIN FETCH mp.user WHERE
mp.matchRoom.id = :matchId AND mp.status = :status.
In `@src/main/java/com/be/sportizebe/domain/match/service/MatchServiceImpl.java`:
- Around line 186-189: The current query in MatchServiceImpl uses
findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc with
List.of(MatchStatus.OPEN, MatchStatus.FULL) which returns both OPEN and FULL
matches; update it to only include MatchStatus.OPEN so the API returns only OPEN
matches as per issue `#71` (i.e., change the status list passed to the repository
call to contain only MatchStatus.OPEN).
- Around line 184-193: The current getMatchesByFacility method hides a
non-existent facility by returning an empty list; before querying
matchRoomRepository, verify the facility exists via sportsFacilityRepository
(e.g., existsById or findById) and if not present throw the existing not-found
error using FacilityErrorCode.FACILITY_NOT_FOUND (or the project's
NotFoundException wrapper), then proceed to call
matchRoomRepository.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc
and map to MatchResponse::from; update getMatchesByFacility to perform this
existence check using sportsFacilityRepository and throw the proper error when
missing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 1551c842-f050-41f9-b800-5b129a557b10
📒 Files selected for processing (6)
.gitignoresrc/main/java/com/be/sportizebe/domain/match/controller/MatchController.javasrc/main/java/com/be/sportizebe/domain/match/repository/MatchParticipantRepository.javasrc/main/java/com/be/sportizebe/domain/match/repository/MatchRoomRepository.javasrc/main/java/com/be/sportizebe/domain/match/service/MatchService.javasrc/main/java/com/be/sportizebe/domain/match/service/MatchServiceImpl.java
| // 매칭 참가자 목록 (N+1 방지 fetch join) | ||
| @Query("SELECT mp FROM MatchParticipant mp JOIN FETCH mp.user WHERE mp.matchRoom.id = :matchId AND mp.status = :status") | ||
| List<MatchParticipant> findAllByMatchRoomIdAndStatusFetch(@Param("matchId") Long matchId, @Param("status") MatchParticipantStatus status); |
There was a problem hiding this comment.
참가자 목록 정렬 기준을 쿼리에 고정해 주세요.
현재 쿼리는 ORDER BY가 없어 응답 순서가 DB 실행 계획에 따라 바뀔 수 있습니다. 사용자 목록을 그대로 노출하는 API라면 가입 순서 등 의도한 기준을 명시하는 편이 안전합니다.
정렬 기준을 명시하는 예시
- `@Query`("SELECT mp FROM MatchParticipant mp JOIN FETCH mp.user WHERE mp.matchRoom.id = :matchId AND mp.status = :status")
+ `@Query`("SELECT mp FROM MatchParticipant mp JOIN FETCH mp.user WHERE mp.matchRoom.id = :matchId AND mp.status = :status ORDER BY mp.joinedAt ASC")
List<MatchParticipant> findAllByMatchRoomIdAndStatusFetch(`@Param`("matchId") Long matchId, `@Param`("status") MatchParticipantStatus status);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/com/be/sportizebe/domain/match/repository/MatchParticipantRepository.java`
around lines 35 - 37, The query in
MatchParticipantRepository.findAllByMatchRoomIdAndStatusFetch lacks an ORDER BY
so result order can vary; update the JPQL to include a deterministic ordering
(e.g., append "ORDER BY mp.createdAt ASC" or "ORDER BY mp.id ASC" depending on
which field represents join order) so participants are consistently returned in
the intended sequence when selecting MatchParticipant JOIN FETCH mp.user WHERE
mp.matchRoom.id = :matchId AND mp.status = :status.
| public List<MatchResponse> getMatchesByFacility(Long facilityId) { | ||
| return matchRoomRepository | ||
| .findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc( | ||
| facilityId, | ||
| List.of(MatchStatus.OPEN, MatchStatus.FULL), | ||
| LocalDateTime.now() | ||
| ) | ||
| .stream() | ||
| .map(MatchResponse::from) | ||
| .toList(); |
There was a problem hiding this comment.
존재하지 않는 facilityId를 빈 목록으로 숨기지 마세요.
지금 구현은 잘못된 facilityId와 "해당 구장에 예정된 매치가 없음"을 동일하게 빈 리스트로 반환합니다. 이미 sportsFacilityRepository와 FacilityErrorCode.FACILITY_NOT_FOUND가 있으니, 조회 전에 구장 존재 여부를 검증해서 404로 구분하는 편이 API 계약상 안전합니다.
구장 존재 여부를 먼저 검증하는 예시
`@Override`
`@Transactional`(readOnly = true)
public List<MatchResponse> getMatchesByFacility(Long facilityId) {
+ if (!sportsFacilityRepository.existsById(facilityId)) {
+ throw new CustomException(FacilityErrorCode.FACILITY_NOT_FOUND);
+ }
+
return matchRoomRepository
.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc(
facilityId,
List.of(MatchStatus.OPEN, MatchStatus.FULL),
LocalDateTime.now()
)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/be/sportizebe/domain/match/service/MatchServiceImpl.java`
around lines 184 - 193, The current getMatchesByFacility method hides a
non-existent facility by returning an empty list; before querying
matchRoomRepository, verify the facility exists via sportsFacilityRepository
(e.g., existsById or findById) and if not present throw the existing not-found
error using FacilityErrorCode.FACILITY_NOT_FOUND (or the project's
NotFoundException wrapper), then proceed to call
matchRoomRepository.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc
and map to MatchResponse::from; update getMatchesByFacility to perform this
existence check using sportsFacilityRepository and throw the proper error when
missing.
| .findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc( | ||
| facilityId, | ||
| List.of(MatchStatus.OPEN, MatchStatus.FULL), | ||
| LocalDateTime.now() |
There was a problem hiding this comment.
구장 조회 API가 요구사항보다 넓은 상태를 반환합니다.
linked issue #71은 특정 구장의 OPEN 매치 목록 조회를 목표로 하고 있는데, Line 186-189는 FULL도 함께 포함합니다. 요구사항 변경이 아니라면 여기서는 OPEN만 조회해야 합니다.
요구사항에 맞추는 예시
return matchRoomRepository
.findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc(
facilityId,
- List.of(MatchStatus.OPEN, MatchStatus.FULL),
+ List.of(MatchStatus.OPEN),
LocalDateTime.now()
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc( | |
| facilityId, | |
| List.of(MatchStatus.OPEN, MatchStatus.FULL), | |
| LocalDateTime.now() | |
| .findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc( | |
| facilityId, | |
| List.of(MatchStatus.OPEN), | |
| LocalDateTime.now() |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/be/sportizebe/domain/match/service/MatchServiceImpl.java`
around lines 186 - 189, The current query in MatchServiceImpl uses
findByFacilityIdAndStatusInAndScheduledAtAfterOrderByScheduledAtAsc with
List.of(MatchStatus.OPEN, MatchStatus.FULL) which returns both OPEN and FULL
matches; update it to only include MatchStatus.OPEN so the API returns only OPEN
matches as per issue `#71` (i.e., change the status list passed to the repository
call to contain only MatchStatus.OPEN).
#️⃣ Issue Number
📝 요약(Summary)
🛠️ PR 유형
어떤 변경 사항이 있나요?
📸스크린샷 (선택)
💬 공유사항 to 리뷰어
✅ PR Checklist
PR이 다음 요구 사항을 충족하는지 확인하세요.
Summary by CodeRabbit
릴리스 노트