Spring-Boot,JPA로 질문/답변 게시판 구현(30)
Spring-Boot, JPA로 질문/잡변 게시판 구현 및 배포
자바지기님 유튜브 강의 정리
5-5 답변 추가(댓글) 및 목록 기능 구현
-
답변을 추가하고 답변 목록을 가져오는 기능을 구현해보자.
-
User나 Question처럼 Answer 클래스를 생성한다.
@Entity @ToString @Getter @Setter public class Answer { @Id @GeneratedValue private Long id; @ManyToOne @JoinColumn(foreignKey = @ForeignKey(name = "fk_answer_writer")) private User writer; @ManyToOne @JoinColumn(foreignKey = @ForeignKey(name = "fk_answer_to_question")) private Question question; @Lob private String contents; private LocalDateTime createDate; public Answer() {} public Answer(User writer, String contents) { this.writer = writer; this.contents = contents; } }
- 컨텐츠같은경우 default로 String으로하면 데이터베이스에서 column길이가 255자이다. 그래서 @Lob 애노테이션을 붙여 255자 이상 작성할 수 있다.
- answer는 항상 question에 종속되어있다. question이 있어야 answer도 있을 수 있다. 관계를 생각해보면 question하나에 여러 answer가 달릴 수 있으므로 many - to - one 관계이다.
-
Answer클래스를 만들었으니 데이터베이스 역할을해줄 repository interface를 만든다.
public interface AnswerRepository extends JpaRepository<Answer, Long> { }
-
또한 AnswerController도 만들어준다.
@Controller @RequestMapping("/questions/{questionId}/answers") public class Answer { }
- url을 생각해볼때, answer는 question과 {id}가 필요하다. 물론 question이 필요없을 수 있지만 question과 answer가 종속 관계이므로 url을 이런식으로 만드는것이 좋은 설계이다.
-
show.html에서 답변하는 form이 있는데 그 부분에서 action url을 설정해주자.
<!-- show.html --> ... <form class="submit-write" method="post" action="/questions//answers"> ... <textarea class="form-control" placeholder="댓글" name="contents"></textarea> <input type="submit" class="btn btn-success pull-right" value="답변하기" /> </form>
-
show.html에서의
name="contents"
를 AnswerController에 매핑해주면@Controller @RequestMapping("/questions/{questionId}/answers") public class Answer { @Autowired; private AnswerRepository answerRepository; @PostMapping("") public String create(@PathVariable Long questionId, String contents, HttpSession session) { if (!HttpSessionUtils.isLoginUser(session)) { System.out.println("Fail about go to update form page : Login failure"); throw new IllegalStateException("로그인 하세요"); } User loginUser = HttpSessionUtils.getUserFromSession(session); Answer answer = new Answer(loginUser,contents); answerRepository.save(answer); return String.format("redirect:/questions/%d", questionId); } }
-
테스트
- 아직 view화면에는 출력이 되지 않았지만 데이터베이스상으로는 데이터가 들어온것을 확인할 수 있다.
-
question과 create_date가 null값이 들어온다.
-
Answer 클래스의 Constructor의 인자로 Question 클래스를 추가한다.
public class Answer { ... public Answer(User writer, Question question, String contents) { this.writer = writer; this.question = question; this.contents = contents; this.createDate = LocalDateTime.now(); } }
-
AnswerController도 Answer Constructor의 인수로 Question클래스를 추가해준다.
public class AnswerController { @Autowired private QuestionRepository questionRepository; ... @PostMapping("") public String create(@PathVariable Long questionId, STring contents, HttpSession session) { ... Question question = questionRepository.findOne(questionId); Answer answer = new Answer(loginUser, question, contents); } }
-
테스트
-
질문의 추가되어있는 답변의 목록을 가져오고 그 목록을 출력할 수 있어야한다. 보통 questionRepository를 통해서 현재 questionId를 가져오고 그것을 통해 답변 목록을 가져올 수 있다.
public class QuestionController { ... @GetMapping("/{id}") public String show(@PathVariable Long id, Model model) { ... answerRepository.findsByQuestionId() } }
-
이렇게 할 수도 있지만 Question클래스에서 Answer클래스를 가지고 있도록 할 수도 있다.
public class Question { ... @OneToMany(mappedBy="question") @OrderBy("id ASC") private List<Answer> answers; }
- Question입장에서 Answer는 one to many관계이므로 어노테이션을 붙여준다. Question클래스에서 many to one으로 answer과 매핑했으므로 그 필드 이름(question)을 써주면된다.
- OrderBy로 정렬 기준과 오름차순,내림차순 정렬을 지정할 수 있다.
- 그러면 QuestionController의 show 메서드에서 answerRepository를 통해 answer목록을 가져올 필요없이 question객체에 answer목록이 담겨져있다.
-
show.html에서 댓글목록을 출력할 수 있다.
<!-- show.html --> ... <div class="qna-comment-slipp-articles"> <article class="article" id="answer-1405"> ... <a href= ...></a> <a href=...></a> ... <p></p> </article> </div>
댓글남기기