Skip to content
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

Q&A 관련 인프라 리팩토링 #686

Merged
merged 17 commits into from
Oct 15, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import com.ddang.ddang.qna.application.exception.QuestionNotFoundException;
import com.ddang.ddang.qna.domain.Answer;
import com.ddang.ddang.qna.domain.Question;
import com.ddang.ddang.qna.domain.repository.QuestionRepository;
import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository;
import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository;
import com.ddang.ddang.user.application.exception.UserNotFoundException;
import com.ddang.ddang.user.domain.User;
import com.ddang.ddang.user.domain.repository.UserRepository;
Expand All @@ -26,7 +26,7 @@ public class AnswerService {

private final ApplicationEventPublisher answerEventPublisher;
private final UserRepository userRepository;
private final JpaQuestionRepository questionRepository;
private final QuestionRepository questionRepository;
private final JpaAnswerRepository answerRepository;

@Transactional
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
import com.ddang.ddang.qna.application.exception.InvalidQuestionerException;
import com.ddang.ddang.qna.application.exception.QuestionNotFoundException;
import com.ddang.ddang.qna.domain.Question;
import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository;
import com.ddang.ddang.qna.domain.repository.QuestionRepository;
import com.ddang.ddang.user.application.exception.UserNotFoundException;
import com.ddang.ddang.user.domain.User;
import lombok.RequiredArgsConstructor;
import com.ddang.ddang.user.domain.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -31,7 +31,7 @@ public class QuestionService {
private final ApplicationEventPublisher questionEventPublisher;
private final AuctionRepository auctionRepository;
private final UserRepository userRepository;
private final JpaQuestionRepository questionRepository;
private final QuestionRepository questionRepository;

@Transactional
public Long create(final CreateQuestionDto questionDto, final String absoluteImageUrl) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.ddang.ddang.qna.domain.repository;

import com.ddang.ddang.qna.domain.Answer;

import java.util.Optional;

public interface AnswerRepository {

Answer save(final Answer answer);

boolean existsByQuestionId(Long questionId);
Copy link
Collaborator

Choose a reason for hiding this comment

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

필수

final이 누락되었습니다

Copy link
Member Author

@JJ503 JJ503 Oct 15, 2023

Choose a reason for hiding this comment

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

추가해두었습니다. 감사합니다.


Optional<Answer> findById(final Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ddang.ddang.qna.domain.repository;

import com.ddang.ddang.qna.domain.Question;

import java.util.List;
import java.util.Optional;

public interface QuestionRepository {

Question save(final Question question);

Optional<Question> findById(final Long id);

List<Question> findAllByAuctionId(final Long auctionId);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.ddang.ddang.qna.infrastructure;

import com.ddang.ddang.qna.domain.Question;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.List;
import java.util.Optional;
Expand All @@ -11,6 +11,14 @@ public interface JpaQuestionRepository extends JpaRepository<Question, Long> {

Optional<Question> findByIdAndDeletedIsFalse(final Long id);

@EntityGraph(attributePaths = {"writer", "answer", "auction", "auction.seller"})
@Query("""
SELECT q
FROM Question q
JOIN FETCH q.writer
LEFT JOIN FETCH q.answer
JOIN FETCH q.auction a
JOIN FETCH a.seller
WHERE q.deleted = false AND a.id = :auctionId
""")
List<Question> findAllByAuctionId(final Long auctionId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.ddang.ddang.qna.infrastructure;

import com.ddang.ddang.qna.domain.Question;
import com.ddang.ddang.qna.domain.repository.QuestionRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
@RequiredArgsConstructor
public class QuestionRepositoryImpl implements QuestionRepository {

private final JpaQuestionRepository jpaQuestionRepository;

@Override
public Question save(final Question question) {
return jpaQuestionRepository.save(question);
}

@Override
public Optional<Question> findById(final Long id) {
return jpaQuestionRepository.findByIdAndDeletedIsFalse(id);
}

@Override
public List<Question> findAllByAuctionId(final Long auctionId) {
return jpaQuestionRepository.findAllByAuctionId(auctionId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.ddang.ddang.qna.application.exception.QuestionNotFoundException;
import com.ddang.ddang.qna.domain.Question;
import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository;
import com.ddang.ddang.qna.domain.repository.QuestionRepository;
import com.ddang.ddang.report.application.dto.CreateQuestionReportDto;
import com.ddang.ddang.report.application.dto.ReadQuestionReportDto;
import com.ddang.ddang.report.application.exception.InvalidQuestionReportException;
Expand All @@ -22,13 +22,13 @@
@RequiredArgsConstructor
public class QuestionReportService {

private final JpaQuestionRepository questionRepository;
private final QuestionRepository questionRepository;
private final UserRepository userRepository;
private final JpaQuestionReportRepository questionReportRepository;

@Transactional
public Long create(final CreateQuestionReportDto questionReportDto) {
final Question question = questionRepository.findByIdAndDeletedIsFalse(questionReportDto.questionId())
final Question question = questionRepository.findById(questionReportDto.questionId())
.orElseThrow(() ->
new QuestionNotFoundException("해당 질문을 찾을 수 없습니다.")
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@
import com.ddang.ddang.qna.application.dto.CreateAnswerDto;
import com.ddang.ddang.qna.domain.Answer;
import com.ddang.ddang.qna.domain.Question;
import com.ddang.ddang.qna.domain.repository.QuestionRepository;
import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository;
import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository;
import com.ddang.ddang.user.domain.Reliability;
import com.ddang.ddang.user.domain.User;
import com.ddang.ddang.user.domain.repository.UserRepository;
import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.List;

@SuppressWarnings("NonAsciiCharacters")
public class AnswerServiceFixture {
Expand All @@ -29,7 +28,7 @@ public class AnswerServiceFixture {
private UserRepository userRepository;

@Autowired
private JpaQuestionRepository questionRepository;
private QuestionRepository questionRepository;

@Autowired
private JpaAnswerRepository answerRepository;
Expand Down Expand Up @@ -87,7 +86,8 @@ void setUp() {
userRepository.save(판매자가_아닌_사용자);

auctionRepository.save(경매);
questionRepository.saveAll(List.of(질문, 답변한_질문));
questionRepository.save(질문);
questionRepository.save(답변한_질문);
answerRepository.save(답변);

답변_등록_요청_dto = new CreateAnswerDto(질문.getId(), "답변 드립니다.", 판매자.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
import com.ddang.ddang.qna.application.dto.ReadUserInQnaDto;
import com.ddang.ddang.qna.domain.Answer;
import com.ddang.ddang.qna.domain.Question;
import com.ddang.ddang.qna.domain.repository.QuestionRepository;
import com.ddang.ddang.qna.infrastructure.JpaAnswerRepository;
import com.ddang.ddang.qna.infrastructure.JpaQuestionRepository;
import com.ddang.ddang.region.domain.Region;
import com.ddang.ddang.region.domain.repository.RegionRepository;
import com.ddang.ddang.user.domain.Reliability;
Expand All @@ -36,7 +36,7 @@ public class QuestionServiceFixture {
private AuctionRepository auctionRepository;

@Autowired
private JpaQuestionRepository questionRepository;
private QuestionRepository questionRepository;

@Autowired
private JpaAnswerRepository answerRepository;
Expand Down Expand Up @@ -166,7 +166,9 @@ void setUp() {
auctionRepository.save(질문과_답변이_존재하는_경매);
auctionRepository.save(종료된_경매);
auctionRepository.save(삭제된_경매);
questionRepository.saveAll(List.of(질문, 질문2, 질문3));
questionRepository.save(질문);
questionRepository.save(질문2);
questionRepository.save(질문3);
answerRepository.saveAll(List.of(답변1, 답변2));

질문_3개_답변_2개가_존재하는_경매_아이디 = 질문과_답변이_존재하는_경매.getId();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.ddang.ddang.qna.infrastructure;

import com.ddang.ddang.configuration.JpaConfiguration;
import com.ddang.ddang.configuration.QuerydslConfiguration;
import com.ddang.ddang.qna.domain.Question;
import com.ddang.ddang.qna.domain.repository.QuestionRepository;
import com.ddang.ddang.qna.infrastructure.fixture.QuestionRepositoryImplFixture;
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;

import java.util.List;
import java.util.Optional;

import static org.assertj.core.api.Assertions.assertThat;

@DataJpaTest
@Import({JpaConfiguration.class, QuerydslConfiguration.class})
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@SuppressWarnings("NonAsciiCharacters")
class QuestionRepositoryImplTest extends QuestionRepositoryImplFixture {

QuestionRepository questionRepository;

@BeforeEach
void setUp(@Autowired final JpaQuestionRepository jpaQuestionRepository) {
questionRepository = new QuestionRepositoryImpl(jpaQuestionRepository);
}

@Test
void 질문을_저장한다() {
// given
final Question question = new Question(경매, 질문자, 질문_내용);

// when
final Question actual = questionRepository.save(question);

// then
assertThat(actual.getId()).isPositive();
}

@Test
void 삭제된_질문은_조회되지_않는다() {
// when
final Optional<Question> actual = questionRepository.findById(삭제된_질문.getId());

// then
assertThat(actual).isEmpty();
}

@Test
void 삭제되지_않은_질문은_조회된다() {
// when
final Optional<Question> actual = questionRepository.findById(질문1.getId());

// then
assertThat(actual).contains(질문1);
}

@Test
void 경매_아이디를_통해_질문과_답변들을_모두_조회한다() {
// when
final List<Question> actual = questionRepository.findAllByAuctionId(질문이_3개_답변이_2개인_경매.getId());

System.out.println(actual.size());
Copy link
Collaborator

Choose a reason for hiding this comment

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

필수

디버깅의 흔적이군요..ㅠㅠ

Copy link
Member Author

Choose a reason for hiding this comment

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

으악 지웠습니다


// then
SoftAssertions.assertSoftly(softAssertions -> {
softAssertions.assertThat(actual).hasSize(3);
softAssertions.assertThat(actual.get(0)).isEqualTo(질문1);
softAssertions.assertThat(actual.get(0).getAnswer()).isEqualTo(답변1);
softAssertions.assertThat(actual.get(1)).isEqualTo(질문2);
softAssertions.assertThat(actual.get(1).getAnswer()).isEqualTo(답변2);
softAssertions.assertThat(actual.get(2)).isEqualTo(질문3);
softAssertions.assertThat(actual.get(2).getAnswer()).isNull();
});
}
}
Loading