Skip to content

Commit

Permalink
[BE] refactor: 리뷰 목록 카테고리 조회 시 네이티브 쿼리를 사용하도록 변경 (#391)
Browse files Browse the repository at this point in the history
* refactor: 리뷰 목록에서 카테고리 표시하는 로직을 네이티브 쿼리로 수정

* refactor: left join을 inner join으로 수정

* test: 실패하는 테스트 수정
  • Loading branch information
skylar1220 authored Aug 19, 2024
1 parent 517e0da commit 6927424
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,12 @@
import org.springframework.stereotype.Repository;
import reviewme.question.domain.OptionItem;
import reviewme.question.domain.OptionType;
import reviewme.question.domain.exception.OptionItemNotFoundException;

@Repository
public interface OptionItemRepository extends JpaRepository<OptionItem, Long> {

List<OptionItem> findAllByOptionType(OptionType optionType);

List<OptionItem> findAllByOptionGroupId(long optionGroupId);

boolean existsByOptionTypeAndId(OptionType optionType, long id);

@Query(value = """
SELECT o.id FROM option_item o
LEFT JOIN checkbox_answer_selected_option c
Expand All @@ -40,7 +35,14 @@ public interface OptionItemRepository extends JpaRepository<OptionItem, Long> {
""", nativeQuery = true)
List<OptionItem> findSelectedOptionItemsByReviewIdAndQuestionId(long reviewId, long questionId);

default OptionItem getOptionItemById(long id) {
return findById(id).orElseThrow(() -> new OptionItemNotFoundException(id));
}
@Query(value = """
SELECT o.* FROM option_item o
INNER JOIN checkbox_answer_selected_option cao
ON cao.selected_option_id = o.id
INNER JOIN checkbox_answer ca
ON cao.checkbox_answer_id = ca.id
WHERE ca.review_id = :reviewId
AND o.option_type = :#{#optionType.name()}
""", nativeQuery = true)
List<OptionItem> findByReviewIdAndOptionType(long reviewId, OptionType optionType);
}
26 changes: 5 additions & 21 deletions backend/src/main/java/reviewme/review/service/ReviewService.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
import reviewme.question.domain.OptionItem;
import reviewme.question.domain.OptionType;
import reviewme.question.repository.OptionItemRepository;
import reviewme.review.domain.CheckboxAnswer;
import reviewme.review.domain.Review;
import reviewme.review.domain.exception.CategoryOptionByReviewNotFoundException;
import reviewme.review.domain.exception.ReviewGroupNotFoundByGroupAccessCodeException;
import reviewme.review.repository.ReviewRepository;
import reviewme.review.service.dto.response.list.ReceivedReviewCategoryResponse;
Expand Down Expand Up @@ -43,26 +41,12 @@ public ReceivedReviewsResponse findReceivedReviews(String groupAccessCode) {
}

private ReceivedReviewResponse createReceivedReviewResponse(Review review) {
CheckboxAnswer checkboxAnswer = review.getCheckboxAnswers()
.stream()
.filter(answer -> optionItemRepository.existsByOptionTypeAndId(
OptionType.CATEGORY, answer.getSelectedOptionIds().get(0).getSelectedOptionId()
))
.findFirst()
.orElseThrow(() -> new CategoryOptionByReviewNotFoundException(review.getId()));
List<OptionItem> categoryOptionItems = optionItemRepository.findByReviewIdAndOptionType(review.getId(),
OptionType.CATEGORY);

List<ReceivedReviewCategoryResponse> categoryResponses =
checkboxAnswer.getSelectedOptionIds()
.stream()
.map(checkBoxAnswerSelectedOptionId -> {
OptionItem optionItem = optionItemRepository.getOptionItemById(
checkBoxAnswerSelectedOptionId.getSelectedOptionId()
);
return new ReceivedReviewCategoryResponse(
optionItem.getId(), optionItem.getContent()
);
})
.toList();
List<ReceivedReviewCategoryResponse> categoryResponses = categoryOptionItems.stream()
.map(optionItem -> new ReceivedReviewCategoryResponse(optionItem.getId(), optionItem.getContent()))
.toList();

return new ReceivedReviewResponse(
review.getId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,17 @@
import reviewme.question.domain.QuestionType;
import reviewme.question.repository.OptionGroupRepository;
import reviewme.question.repository.OptionItemRepository;
import reviewme.question.repository.QuestionRepository;
import reviewme.review.domain.CheckboxAnswer;
import reviewme.review.domain.Review;
import reviewme.review.domain.exception.ReviewGroupNotFoundByGroupAccessCodeException;
import reviewme.review.service.dto.response.list.ReceivedReviewCategoryResponse;
import reviewme.review.service.dto.response.list.ReceivedReviewsResponse;
import reviewme.review.repository.CheckboxAnswerRepository;
import reviewme.question.repository.QuestionRepository;
import reviewme.review.repository.ReviewRepository;
import reviewme.review.service.dto.response.list.ReceivedReviewsResponse;
import reviewme.reviewgroup.domain.ReviewGroup;
import reviewme.reviewgroup.repository.ReviewGroupRepository;
import reviewme.support.ServiceTest;
import reviewme.template.domain.Section;
import reviewme.template.domain.Template;
import reviewme.template.domain.VisibleType;
import reviewme.template.repository.SectionRepository;
import reviewme.template.repository.TemplateRepository;

Expand Down Expand Up @@ -95,57 +92,4 @@ class ReviewServiceTest {
// then
assertThat(response.reviews()).hasSize(2);
}

@Test
void 리뷰_목록을_반환할때_선택한_카테고리만_함께_반환한다() {
// given
String groupAccessCode = "groupAccessCode";
Question question1 = questionRepository.save(
new Question(true, QuestionType.CHECKBOX, "프로젝트 기간 동안, 팀원의 강점이 드러났던 순간을 선택해주세요. (1~2개)", null, 1)
);
Question question2 = questionRepository.save(
new Question(true, QuestionType.CHECKBOX, "커뮤니케이션, 협업 능력에서 어떤 부분이 인상 깊었는지 선택해주세요. (1개 이상)", null, 2)
);

OptionGroup categoryOptionGroup = optionGroupRepository.save(new OptionGroup(question1.getId(), 1, 2));
OptionGroup keywordOptionGroup = optionGroupRepository.save(new OptionGroup(question2.getId(), 1, 10));

OptionItem categoryOption1 = new OptionItem("커뮤니케이션 능력 ", categoryOptionGroup.getId(), 1, OptionType.CATEGORY);
OptionItem categoryOption2 = new OptionItem("시간 관리 능력", categoryOptionGroup.getId(), 2, OptionType.CATEGORY);
OptionItem keywordOption = new OptionItem("얘기를 잘 들어줘요", keywordOptionGroup.getId(), 2, OptionType.KEYWORD);
optionItemRepository.saveAll(List.of(categoryOption1, categoryOption2, keywordOption));

Section section1 = sectionRepository.save(
new Section(VisibleType.ALWAYS, List.of(question1.getId()), null, "팀원과 함께 한 기억을 떠올려볼게요.", 1)
);
Section section2 = sectionRepository.save(
new Section(VisibleType.CONDITIONAL, List.of(question2.getId()), null, "선택한 순간들을 바탕으로 리뷰를 작성해볼게요.", 1)
);
Template template = templateRepository.save(new Template(List.of(section1.getId(), section2.getId())));

ReviewGroup reviewGroup = reviewGroupRepository.save(
new ReviewGroup("커비", "리뷰미", "reviewRequestCode", groupAccessCode)
);
CheckboxAnswer categoryAnswer = new CheckboxAnswer(question1.getId(), List.of(categoryOption1.getId()));
CheckboxAnswer keywordAnswer = new CheckboxAnswer(question2.getId(), List.of(keywordOption.getId()));
reviewRepository.save(
new Review(template.getId(), reviewGroup.getId(), List.of(), List.of(categoryAnswer, keywordAnswer))
);

// when
ReceivedReviewsResponse response = reviewService.findReceivedReviews(groupAccessCode);

// then
List<String> categoryContents = optionItemRepository.findAllByOptionType(OptionType.CATEGORY)
.stream()
.map(OptionItem::getContent)
.toList();

assertThat(response.reviews())
.map(review -> review.categories()
.stream()
.map(ReceivedReviewCategoryResponse::content)
.toList())
.allSatisfy(content -> assertThat(categoryContents).containsAll(content));
}
}

0 comments on commit 6927424

Please sign in to comment.