Skip to content

[feat] #145 매칭 후보 조회 로직에 QueryDSL 도입 및 최적화#146

Merged
2hyunjinn merged 9 commits intomainfrom
feat/#145
Jun 16, 2025
Merged

[feat] #145 매칭 후보 조회 로직에 QueryDSL 도입 및 최적화#146
2hyunjinn merged 9 commits intomainfrom
feat/#145

Conversation

@2hyunjinn
Copy link
Member

@2hyunjinn 2hyunjinn commented Jun 16, 2025

📌 PR 제목

[feat] #145 매칭 후보 조회 로직에 QueryDSL 도입 및 최적화

📌 PR 내용

  • QueryDSL 도입: 기존 JPQL 문자열 기반 쿼리를 QueryDSL 메서드 체이닝으로 전환하여 동적 필터링, 조건 조합 편의성 확보
  • 서브쿼리 캐싱: findBestCandidateByPriority 호출 시 매번 실행되던 이미 매칭된 대상 조회 서브쿼리를 서비스 레벨에서 한 번만 실행하도록 변경해 불필요한 DB 호출을 절감

🛠 작업 내용

  • QueryDSL 기반 MatchingRepositoryImpl 구현
  • Q-타입(QParticipant, QMatching, QUser) 활용한 동적 쿼리 작성
  • .where(...) 체이닝으로 null 조건 자동 무시
  • MatchingServiceImpl에 QueryDSL 도입 로직 반영
  • MatchingRepository에 findExcludeIds(Long applicantId) 메서드 추가: 서브쿼리 캐싱
  • findMatchingCandidatesDsl 시그니처 수정: List excludedIds 파라미터 추가
  • findBestCandidateByPriority 내부에서 excludedIds를 한 번만 조회하도록 리팩토링

🔍 관련 이슈

Closes #145

📸 스크린샷 (Optional)

image

📚 레퍼런스 (Optional)

https://reprisal.tistory.com/178
https://adjh54.tistory.com/484

Summary by CodeRabbit

  • New Features

    • Improved participant matching logic to exclude previously matched candidates, enhancing the accuracy of match suggestions.
    • Added support for more advanced and efficient matching queries using QueryDSL.
  • Chores

    • Updated build configuration to support QueryDSL and annotation processing for better query handling.
  • Bug Fixes

    • Corrected a typo in the project group identifier.
  • Tests

    • Updated tests to reflect changes in matching logic and candidate exclusion handling.

@2hyunjinn 2hyunjinn self-assigned this Jun 16, 2025
@2hyunjinn 2hyunjinn added the feat Extra attention is needed label Jun 16, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jun 16, 2025

Walkthrough

This change migrates the matching candidate query logic from a JPQL-based approach to a QueryDSL-based custom repository implementation. It introduces new interfaces and classes for QueryDSL integration, updates service and test layers to use the new methods, and adds required build and configuration changes for QueryDSL support.

Changes

File(s) Change Summary
build.gradle Corrected group ID, added QueryDSL and Jakarta Persistence dependencies, configured annotation processor source sets.
src/main/java/org/festimate/team/domain/matching/repository/MatchingRepository.java Removed JPQL query method; now extends new custom interface.
src/main/java/org/festimate/team/domain/matching/repository/MatchingRepositoryCustom.java Added new custom repository interface with QueryDSL method signatures.
src/main/java/org/festimate/team/domain/matching/repository/MatchingRepositoryImpl.java Added new implementation for custom repository using QueryDSL for candidate and exclusion queries.
src/main/java/org/festimate/team/domain/matching/service/impl/MatchingServiceImpl.java Updated service to use new QueryDSL-based repository methods, passing exclusion list.
src/main/java/org/festimate/team/infra/config/QuerydslConfig.java Added Spring configuration for QueryDSL's JPAQueryFactory bean.
src/test/java/org/festimate/team/domain/matching/service/impl/MatchingServiceImplTest.java Updated tests to use new repository methods and handle exclusion list in stubbing.

Sequence Diagram(s)

sequenceDiagram
    participant Service as MatchingServiceImpl
    participant Repo as MatchingRepository (with Custom)
    participant Impl as MatchingRepositoryImpl
    participant DB as Database

    Service->>Repo: findExcludeIds(applicantId)
    Repo->>Impl: findExcludeIds(applicantId)
    Impl->>DB: Query completed matchings for applicantId
    Impl-->>Repo: List<Long> (excludedIds)
    Repo-->>Service: List<Long> (excludedIds)

    Service->>Repo: findMatchingCandidatesDsl(applicantId, typeResult, gender, festivalId, pageable, excludedIds)
    Repo->>Impl: findMatchingCandidatesDsl(...)
    Impl->>DB: Query for candidates with filters and exclusions
    Impl-->>Repo: List<Participant>
    Repo-->>Service: List<Participant>
Loading

Assessment against linked issues

Objective Addressed Explanation
Replace JPQL-based candidate query with QueryDSL implementation (custom interface, implementation) (#145)
Inject JPAQueryFactory via configuration for QueryDSL (#145)
Update service and tests to use new QueryDSL-based repository methods (#145)
Add QueryDSL dependencies and configure annotation processing in build system (#145)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Possibly related PRs

Poem

In the warren where queries hop and play,
We swapped old JPQL for QueryDSL today.
With beans and configs, the types are strong,
Matching candidates now bounce along!
Exclusions in tow, the tests all agree—
This code’s as hoppy as a rabbit can be!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1918e63 and 66a3a39.

📒 Files selected for processing (1)
  • src/main/java/org/festimate/team/infra/config/QuerydslConfig.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/org/festimate/team/infra/config/QuerydslConfig.java
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: test
  • GitHub Check: Build Test
✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions
Copy link

github-actions bot commented Jun 16, 2025

Test Results

46 tests   46 ✅  1s ⏱️
10 suites   0 💤
10 files     0 ❌

Results for commit 66a3a39.

♻️ This comment has been updated with latest results.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
build.gradle (1)

71-78: Consider using sourceSets.main.java.srcDirs += file("…") instead of redefining the whole block

Redefining srcDir 'src/main/java' manually makes the build file harder to scan and can break IDE auto-import helpers if the convention ever changes. A minimal additive approach keeps intent clear:

sourceSets.main.java.srcDirs += 'build/generated/sources/annotationProcessor/java/main'

Not blocking, but simplifies maintenance.

src/main/java/org/festimate/team/domain/matching/service/impl/MatchingServiceImpl.java (1)

93-105: Reuse immutable objects inside the loop

PageRequest.of(0, 1) is rebuilt on every iteration even though it’s constant. Extracting it once clarifies intent and avoids needless object creation (micro-optimisation but free and readable):

+        PageRequest singleCandidate = PageRequest.of(0, 1);
         for (TypeResult priorityType : priorities) {
             Optional<Participant> candidate = matchingRepository.findMatchingCandidatesDsl(
                     participant.getParticipantId(),
                     priorityType,
                     myGender,
                     festivalId,
-                    PageRequest.of(0, 1),
+                    singleCandidate,
                     excludedIds
             ).stream().findFirst();
src/main/java/org/festimate/team/domain/matching/repository/MatchingRepository.java (1)

3-8: Remove unused imports.

TypeResult (l.5) and Pageable (l.7) are no longer referenced; keep the file clean to avoid compiler warnings.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1022668 and 1918e63.

📒 Files selected for processing (7)
  • build.gradle (2 hunks)
  • src/main/java/org/festimate/team/domain/matching/repository/MatchingRepository.java (1 hunks)
  • src/main/java/org/festimate/team/domain/matching/repository/MatchingRepositoryCustom.java (1 hunks)
  • src/main/java/org/festimate/team/domain/matching/repository/MatchingRepositoryImpl.java (1 hunks)
  • src/main/java/org/festimate/team/domain/matching/service/impl/MatchingServiceImpl.java (1 hunks)
  • src/main/java/org/festimate/team/infra/config/QuerydslConfig.java (1 hunks)
  • src/test/java/org/festimate/team/domain/matching/service/impl/MatchingServiceImplTest.java (7 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: test
🔇 Additional comments (4)
src/main/java/org/festimate/team/domain/matching/service/impl/MatchingServiceImpl.java (1)

93-105: Verify that passing the applicant’s gender matches repository semantics

findMatchingCandidatesDsl receives Gender gender.
Here you forward the applicant’s own gender (myGender).
Double-check that the repository interprets this parameter as “exclude same gender” rather than “include only same gender”; otherwise candidates of the wrong gender may be returned or filtered out.

If the repository expects the opposite gender, invert before calling:

Gender targetGender = myGender == Gender.MAN ? Gender.WOMAN : Gender.MAN;

Marking for verification.

src/main/java/org/festimate/team/domain/matching/repository/MatchingRepositoryCustom.java (1)

10-21: Interface looks good

Clear separation of custom operations; names are self-descriptive.

src/main/java/org/festimate/team/domain/matching/repository/MatchingRepository.java (1)

15-15: Good split of responsibilities.

Delegating complex candidate-search logic to MatchingRepositoryCustom keeps this interface focused on core Matching queries.

src/main/java/org/festimate/team/domain/matching/repository/MatchingRepositoryImpl.java (1)

47-63: ```shell
#!/bin/bash
set -e

Locate Participant entity

participant_file=$(fd Participant.java | head -n1)
echo "Participant file: $participant_file"
grep -R "private.*Matching" -n "$participant_file" || echo "No direct Matching references found in Participant."

Locate Matching entity

matching_file=$(fd Matching.java | head -n1)
echo "Matching file: $matching_file"
grep -R "private.*Participant" -n "$matching_file" || echo "No direct Participant references found in Matching."
grep -R "status" -n "$matching_file" || echo "No status field found in Matching."

Inspect repository for Q-class usage

repo_file=$(fd MatchingRepositoryImpl.java | head -n1)
echo "Repository file: $repo_file"
grep -R "QParticipant" -n "$repo_file" || echo "No QParticipant instantiation found."
grep -R "QMatching" -n "$repo_file" || echo "No QMatching instantiation found."


</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

@2hyunjinn 2hyunjinn merged commit e4b0c4d into main Jun 16, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat Extra attention is needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 매칭 후보 조회 로직에 QueryDSL 도입 및 최적화

1 participant

Comments