diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetGetRepositoryCustom.java b/src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetGetRepositoryCustom.java new file mode 100644 index 0000000..fa46869 --- /dev/null +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/repository/ProblemSetGetRepositoryCustom.java @@ -0,0 +1,90 @@ +package com.moplus.moplus_server.domain.problemset.repository; + +import static com.moplus.moplus_server.admin.publish.domain.QPublish.*; +import static com.moplus.moplus_server.domain.concept.domain.QConceptTag.*; +import static com.moplus.moplus_server.domain.problem.domain.problem.QProblem.*; +import static com.moplus.moplus_server.domain.problem.domain.childProblem.QChildProblem.*; + +import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSetGetResponse; +import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSummaryResponse; +import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; +import com.querydsl.core.Tuple; +import com.querydsl.jpa.impl.JPAQueryFactory; +import java.time.LocalDate; +import java.util.*; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +@Repository +@RequiredArgsConstructor +public class ProblemSetGetRepositoryCustom { + + private final JPAQueryFactory queryFactory; + + public ProblemSetGetResponse getProblemSet(ProblemSet problemSet) { + // 발행 날짜 조회 쿼리 + List publishedDates = queryFactory + .select(publish.publishedDate) + .from(publish) + .where(publish.problemSetId.eq(problemSet.getId())) + .fetch(); + + // 문항 및 새끼문항 조회 + List problemData = queryFactory + .select( + problem.id, + problem.problemCustomId.id, + problem.title.title, + problem.memo, + problem.mainProblemImageUrl + ) + .from(problem) + .leftJoin(problem.childProblems, childProblem) // 자식 문제 JOIN + .where(problem.id.in(problemSet.getProblemIds())) + .distinct() + .fetch(); + + // 문항 및 새끼 문항의 개념 태그 조회 + List allProblemIds = problemSet.getProblemIds(); // 문제 ID 목록 + List childProblemIds = queryFactory + .select(childProblem.id) + .from(problem) + .join(problem.childProblems, childProblem) + .where(problem.id.in(allProblemIds)) + .fetch(); + + Set allProblemAndChildProblemIds = new HashSet<>(allProblemIds); + allProblemAndChildProblemIds.addAll(childProblemIds); // 문제 + 자식 문제 ID 합침 + + // 문항 및 자식 문항의 개념 태그 조회 + Map> conceptTagMap = queryFactory + .select(problem.id, conceptTag.name) + .from(problem) + .leftJoin(conceptTag) + .on(conceptTag.id.in(problem.conceptTagIds)) + .where(problem.id.in(allProblemAndChildProblemIds)) // 문제 + 자식 문제 ID + .fetch() + .stream() + .collect( + HashMap::new, + (map, tuple) -> map + .computeIfAbsent(tuple.get(problem.id), k -> new HashSet<>()) + .add(tuple.get(conceptTag.name)), + HashMap::putAll + ); + + List problemSummaries = problemData.stream() + .map(tuple -> ProblemSummaryResponse.builder() + .problemId(tuple.get(problem.id)) + .problemCustomId(tuple.get(problem.problemCustomId.id)) + .problemTitle(tuple.get(problem.title.title)) + .memo(tuple.get(problem.memo)) + .mainProblemImageUrl(tuple.get(problem.mainProblemImageUrl)) + .tagNames(conceptTagMap.getOrDefault(tuple.get(problem.id), new HashSet<>())) // 태그 매핑 + .build() + ) + .toList(); + + return ProblemSetGetResponse.of(problemSet, publishedDates, problemSummaries); + } +} \ No newline at end of file diff --git a/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java index ef66f46..cdf0dfd 100644 --- a/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java +++ b/src/main/java/com/moplus/moplus_server/domain/problemset/service/ProblemSetGetService.java @@ -1,22 +1,11 @@ package com.moplus.moplus_server.domain.problemset.service; -import com.moplus.moplus_server.domain.concept.domain.ConceptTag; -import com.moplus.moplus_server.domain.concept.repository.ConceptTagRepository; -import com.moplus.moplus_server.domain.problem.domain.problem.Problem; -import com.moplus.moplus_server.domain.problem.repository.ProblemRepository; import com.moplus.moplus_server.domain.problemset.domain.ProblemSet; import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSetGetResponse; -import com.moplus.moplus_server.admin.problemset.dto.response.ProblemSummaryResponse; +import com.moplus.moplus_server.domain.problemset.repository.ProblemSetGetRepositoryCustom; import com.moplus.moplus_server.domain.problemset.repository.ProblemSetRepository; -import com.moplus.moplus_server.admin.publish.domain.Publish; -import com.moplus.moplus_server.domain.publish.repository.PublishRepository; import com.moplus.moplus_server.global.error.exception.BusinessException; import com.moplus.moplus_server.global.error.exception.ErrorCode; -import java.time.LocalDate; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,9 +15,7 @@ public class ProblemSetGetService { private final ProblemSetRepository problemSetRepository; - private final ProblemRepository problemRepository; - private final ConceptTagRepository conceptTagRepository; - private final PublishRepository publishRepository; + private final ProblemSetGetRepositoryCustom problemSetGetRepositoryCustom; @Transactional(readOnly = true) public ProblemSetGetResponse getProblemSet(Long problemSetId) { @@ -36,23 +23,6 @@ public ProblemSetGetResponse getProblemSet(Long problemSetId) { if (problemSet.isDeleted()) { throw new BusinessException(ErrorCode.DELETE_PROBLEM_SET_GET_ERROR); } - List publishedDates = publishRepository.findByProblemSetId(problemSetId).stream() - .map(Publish::getPublishedDate) - .toList(); - - List problemSummaries = new ArrayList<>(); - for (Long problemId : problemSet.getProblemIds()) { - Problem problem = problemRepository.findByIdElseThrow(problemId); - Set tagNames = new HashSet<>( - conceptTagRepository.findAllByIdsElseThrow(problem.getConceptTagIds()) - .stream() - .map(ConceptTag::getName) - .toList()); - problem.getChildProblems().stream() - .map(childProblem -> conceptTagRepository.findAllByIdsElseThrow(childProblem.getConceptTagIds())) - .forEach(conceptTags -> tagNames.addAll(conceptTags.stream().map(ConceptTag::getName).toList())); - problemSummaries.add(ProblemSummaryResponse.of(problem, tagNames)); - } - return ProblemSetGetResponse.of(problemSet, publishedDates, problemSummaries); + return problemSetGetRepositoryCustom.getProblemSet(problemSet); } }