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;
...
}
'Study > SpringBoot' 카테고리의 다른 글
[스프링부트 개념정리] Ioc, DI란 (0) | 2022.06.16 |
---|---|
[Springboot] AOP처리 - 유효성검사 (0) | 2022.06.03 |
[Springboot] 프로필 사진 변경 (0) | 2022.05.31 |
[Springboot] 좋아요 기능 추가 - 2 뷰에 렌더링 (0) | 2022.05.29 |
[Springboot] 좋아요 기능 추가 - 1 Model 및 쿼리 작업 (0) | 2022.05.28 |