Cooper's devlog

6-4. 질문 목록에 답변 수 보여주기 기능 추가 본문

Programming/Spring-boot

6-4. 질문 목록에 답변 수 보여주기 기능 추가

cooper_dev 2020. 8. 3. 17:33

1. 강의 링크

https://www.youtube.com/watch?v=E_Iov1Vd2TU&list=PLqaSEyuwXkSppQAjwjXZgKkjWbFoUdNXC&index=51


2. 학습 목표

  • 질문 목록에서 답변 수를 보여주려면 성능상의 이슈가 발생
  • 이 이슈를 해결하는 방법: Question 테이블에 답변 수를 관리하는 방법에 대해 다룬다.

3. 과정

댓글 갯수 count 방법 : select count(*) from answer where question_id = 3;

문제점 : 글이 많아질수록 각각의 글에 대한 query를 작성해야 한다.(query문 요청이 많을수록 성능 저하)

해결법 : 내부 로직을 통해서 값을 전달해주는 방식으로 접근

 

1. Question.java 상단부(vo)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package net.slipp.domain;
 
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
 
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
 
import org.hibernate.type.LocalDateTimeType;
 
import com.fasterxml.jackson.annotation.JsonProperty;
 
@Entity
public class Question {
    @Id
    @GeneratedValue
    @JsonProperty
    private Long id;
    
    @ManyToOne
    @JoinColumn(foreignKey = @ForeignKey(name="fk_question_writer"))
    @JsonProperty
    private User writer;
    
    @JsonProperty
    private String title;
    
    @Lob //상당히 긴 내용을 첨가할 경우
    @JsonProperty
    private String contents;
    
    @JsonProperty
    private Integer countOfAnswer = 0;
    
    private LocalDateTime createDate;
    
    @OneToMany(mappedBy = "question")
    @OrderBy("id DESC")
    private List<Answer> answers;
 
  • countOfAnswer = 0으로 column 추가하기

2. import.sql(defualt data)

1
INSERT INTO QUESTION (ID, WRITER_ID, TITLE, CONTENTS, CREATE_DATE, COUNT_OF_ANSWER) VALUES (11'제목1','해당 내용1',CURRENT_TIMESTAMP(), 0);
 
  • COUNT_OF_ANSWER를 추가 컬럼 대입하기

 

3. ApiAnswerController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package net.slipp.web;
 
import javax.servlet.http.HttpSession;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import net.slipp.domain.Answer;
import net.slipp.domain.AnswerRepository;
import net.slipp.domain.Question;
import net.slipp.domain.QuestionRepository;
import net.slipp.domain.Result;
import net.slipp.domain.User;
 
@RestController
@RequestMapping("/api/questions/{questionId}/answers")
public class ApiAnswerController {
    
    @Autowired
    private QuestionRepository questionRepository; 
    
    @Autowired
    private AnswerRepository answerRepository; 
    
    @PostMapping("")
    public Answer create(@PathVariable Long questionId, String contents, HttpSession session) {
        if(!HttpSessionUtils.isLoginUser(session)) {
            return null;
        }
        
        User loginUser = HttpSessionUtils.getUserFromSession(session);
        Question question = questionRepository.findById(questionId).get();
        Answer answer = new Answer(loginUser, question ,contents);
        question.addAnswer();
        
        return answerRepository.save(answer);
    }
    
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Long questionId,@PathVariable Long id,HttpSession session) {
                    
            if(!HttpSessionUtils.isLoginUser(session)) {
                        
                        return Result.fail("로그인 해야합니다");
                    }
            User loginUser = HttpSessionUtils.getUserFromSession(session);
            Answer answer = answerRepository.findById(id).get();
            
            if(!answer.isSameWriter(loginUser)) {
                return Result.fail("본인 글만  삭제할수있습니다");
            }
 
            answerRepository.delete(answer);
            Question question = questionRepository.findById(questionId).get();
            question.deleteAnswer();
            
            questionRepository.save(question);
            
            return Result.ok();
            
            
    }  
}
 
 

38line : question.addAnswer() 추가

59line : question.deleteAnswer() 추가

 

4. Question.java 하단부(vo)

1
2
3
4
5
6
7
8
    //댓글 수 증가 감소
    public void addAnswer() {
        this.countOfAnswer += 1;
    }
    
    public void deleteAnswer() {
        this.countOfAnswer -= 1;
    }
 
addAnswer() : 댓글 수 추가 method
deleteAnswer() : 댓글 수 감소 method
 

 

Comments