-
Notifications
You must be signed in to change notification settings - Fork 0
[refactor/#91] 문항세트 조회 api 리팩토링 #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생했어요!
JPA의 영속성 컨텍스트 저장 매커니즘을 한번 살펴보면 좋을 것 같아요
private final ProblemRepository problemRepository; | ||
private final ConceptTagRepository conceptTagRepository; | ||
private final PublishRepository publishRepository; | ||
private final ProblemSetGetRepositoryCustom problemSetGetRepositoryCustom; | ||
|
||
@Transactional(readOnly = true) | ||
public ProblemSetGetResponse getProblemSet(Long problemSetId) { | ||
ProblemSet problemSet = problemSetRepository.findByIdElseThrow(problemSetId); | ||
if (problemSet.isDeleted()) { | ||
throw new BusinessException(ErrorCode.DELETE_PROBLEM_SET_GET_ERROR); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
명시적인 예외 클래스로 만들어주실 수 있을까요?
DeletedException 이라던지
|
||
// 문항 및 새끼 문항의 개념 태그 조회 | ||
List<Long> allProblemIds = problemSet.getProblemIds(); // 문제 ID 목록 | ||
List<Long> childProblemIds = queryFactory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위에서 problem과 childproblem을 fetch join해와서 한번더 조회를 하지않아도 될것 같아요
problem.title.title, | ||
problem.memo, | ||
problem.mainProblemImageUrl | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JPA는 select 문에 조회하고 싶은 엔티티를 넣어야지 영속성 컨텍스트에 반영해요
fetch join을 해서 영속성 컨텍스트에 넣어주거나 select 문에 엔티티를 선언해주어야해요
.fetch(); | ||
|
||
Set<Long> allProblemAndChildProblemIds = new HashSet<>(allProblemIds); | ||
allProblemAndChildProblemIds.addAll(childProblemIds); // 문제 + 자식 문제 ID 합침 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
문항과 새끼문항의 아이디를 set으로 합치는 이유는 어떤걸가요?
.from(problem) | ||
.leftJoin(conceptTag) | ||
.on(conceptTag.id.in(problem.conceptTagIds)) | ||
.where(problem.id.in(allProblemAndChildProblemIds)) // 문제 + 자식 문제 ID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
문항 테이블에서 새끼 문항 id로 검색하는것 같은데요?
.memo(tuple.get(problem.memo)) | ||
.mainProblemImageUrl(tuple.get(problem.mainProblemImageUrl)) | ||
.tagNames(conceptTagMap.getOrDefault(tuple.get(problem.id), new HashSet<>())) // 태그 매핑 | ||
.build() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DTO에 대한 정보가 repository까지 내려오는거는 유지보수 관점에서 좋지 않은것 같아요
DTO가 바뀌면 repository까지 수정하러 내려와야할 것 같네요
mapper로직을 넣어주거나 DTO 자체를 repository가 모르게 구성하는건 어떨까요?
💡 Issue
📄 Description
기존 쿼리
문항세트에 속한 문항들을 개별 조회
문항에 속한 개념태그들을 개별 조회
SELECT절에 엔티티가 포함되어, 불필요한 필드들도 조회
위와 같은 문제점들 때문에, 문항세트에 속한 문항의 개수와 문항에 속한 개념태그들의 수가 늘어남에 따라 쿼리의 개수도 배로 증가하는 구조였습니다.
개선된 쿼리
문항세트에 속한 문항ID들을 조회합니다.
조회한 문항ID들을 IN절로 문항 필드들을 조회합니다 (여기서 새끼문항과 join을 통해 새끼문항의 ID들도 가져옵니다).
새끼문항에 속한 개념태그ID들 + 조회한 문항에 속한 개념태그ID들을 IN절로 조회합니다.
SELECT절에 필요한 필드만 명시적으로 남겼습니다.
최종적으로 총 4번의 쿼리로 개선했습니다.
💬 To Reviewers