반응형

Comment.class

- Comment 와 User는 n:1관계다 (1명의 유저는 여러개의 댓글을 쓸 수 있으므로
- 또한 하나의 이미지에 여러 댓글이 달릴 수 있으므로 Comment 와 Image는 n:1이다.
- ManyToOne에서는 EAGER 가 디폴트
  =>왜냐하면 1개 댓글에는 user나 image 정보가 1개뿐이라서 join해서 가져와도 db에 무리가 없다.

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Comment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(length = 100, nullable = false)
    private String content;

    @JsonIgnoreProperties("{images}")
    @JoinColumn(name = "userId")
    @ManyToOne(fetch =FetchType.EAGER) 
    private User user;

    @JoinColumn(name = "imageId")
    @ManyToOne(fetch = FetchType.EAGER)
    private Image image;


    private LocalDateTime createDate;

    @PrePersist
    public void createDate(){
        this.createDate = LocalDateTime.now();
    }
}

 

CommentService.class

@RequiredArgsConstructor
@Service
public class CommentService {

    private final CommentRepository commentRepository;
    private final UserRepository userRepository;

    @Transactional
    public Comment commentSave(String content, int imageId, int userId){

        Image image = new Image();
        image.setId(imageId);
        
        User userEntity = userRepository.findById(userId).orElseThrow(()->{
            return new CustomApiException("유저 아이디를 찾을 수 없습니다.");
        });

        Comment comment = new Comment();
        comment.setContent(content);
        comment.setImage(image);
        comment.setUser(userEntity);

        return commentRepository.save(comment);


}

 

CommentApiController.class
- CommentDto commentDto만 쓰는건 x-www-urlencoded 로 받는거기 때문에
    json 데이터 받으려면  @RequestBody  붙여줘야한다.

@RequiredArgsConstructor
@RestController
public class CommentApiController {

    private final CommentService commentService;

    @PostMapping("/api/comment")
    public ResponseEntity<?> commentSave(@RequestBody CommentDto commentDto,
                                         @AuthenticationPrincipal PrincipalDetails principalDetails){

        Comment comment = commentService.commentSave(commentDto.getContent(), commentDto.getImageId(), principalDetails.getUser().getId());
        return new ResponseEntity<>(new CMRespDto<>(1, "댓글쓰기성공", comment), HttpStatus.CREATED);
    }

}

 

story.js
  - 댓글을 달고자하는 이미지의 id를 전달해줘서 클릭시 addComment() 함수가 실행되도록 한다.
- 댓글 작성하고 DB에 댓글이 저장되고, 그 내용이 storyCommentList에 append되야한다 

...

<div id="storyCommentList-${image.id}">`;

                image.comments.forEach((comment)=>{
                    item +=`<div class="sl__item__contents__comment" id="storyCommentItem-${comment.id}">
                    <p>
                        <b> ${image.user} :</b> ${comment.content}
                    </p>

                    <button onclick="deleteComment(${comment.id})">
                        <i class="fas fa-times"></i>
                    </button>
                </div>`;

                });


            item += `
         </div>

         <div class="sl__item__input">
			<input type="text" placeholder="댓글 달기..." id="storyCommentInput-${image.id}" />
             <button type="button" onClick="addComment(${image.id} )">게시</button>
         </div>

     </div>
     </div>`;
function addComment(imageId) {

   let commentInput = $(`#storyCommentInput-${imageId}`);

       let commentList = $(`#storyCommentList-${imageId}`);

       let data = {
           imageId: imageId,
          content: commentInput.val()
    };

   if (data.content === "") {
      alert("댓글을 작성해주세요!");
      return;
   }

   $.ajax({
       type:"post",
       url:"/api/comment",
       data:JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: "json"
   }).done(res=>{
       console.log("성공", res);

        let comment = res.data;

        console.log(comment);

        let content = `
          <div class="sl__item__contents__comment" id="storyCommentItem-${comment.id}">
            <p>
              <b>${comment.user.username} :</b>
              ${comment.content}
            </p>
            <button><i class="fas fa-times"></i></button>
          </div>
        `;
        commentList.prepend(content);
   }).fail(error=>{
       console.log("오류", error);
   });

   commentInput.val(""); //인풋필드를 깨끗하게 비워준다.
}

 

CommentDto

- addComment()가 전달하는 값이 imageId와 content 뿐이기에 이 데이터를 받는 dto가 필요하다. 

@Data
public class CommentDto {
    private String content;
    private int imageId;

}

 

ImageApiController의 imageStory 함수가 등록한 댓글을 뿌려줘야 하는데, 

Image.class
현재 Image 객체에는 댓글관련 정보를 들고 있지 않기 때문에 관련 컬럼을 만들어주고, 양방향 매핑을 해줘야한다. 
- 한 이미지에 여러 comments가 붙기때문에 OneToMany 어노테이션을 붙여준다.
-  이미지를 가져올때 Comment의 이미지 정보를 가져올 필요가 없으므로 JsonIgnore해준다. 

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Image {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

   ...

    //댓글
    @OrderBy("id DESC")
    @JsonIgnoreProperties({"image"})
    @OneToMany(mappedBy = "image")
    private List<Comment>comments;

   ...
}

+ Recent posts