Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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,12 +9,15 @@
import com.example.solidconnection.type.BoardCode;
import com.example.solidconnection.type.PostCategory;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.EnumUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_POST_CATEGORY;

@Service
@RequiredArgsConstructor
public class BoardService {
Expand All @@ -28,12 +31,11 @@ private String validateCode(String code) {
}
}

private PostCategory validatePostCategory(String postCategory) {
try {
return PostCategory.valueOf(postCategory);
} catch (IllegalArgumentException ex) {
throw new CustomException(ErrorCode.INVALID_POST_CATEGORY);
private PostCategory validatePostCategory(String category){
if(!EnumUtils.isValidEnum(PostCategory.class, category)){
throw new CustomException(INVALID_POST_CATEGORY);
}
return PostCategory.valueOf(category);
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.example.solidconnection.comment.controller;

import com.example.solidconnection.comment.dto.*;
import com.example.solidconnection.comment.service.CommentService;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityRequirements;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;

import static com.example.solidconnection.config.swagger.SwaggerConfig.ACCESS_TOKEN;

@RestController
@RequiredArgsConstructor
@RequestMapping("/posts")
@SecurityRequirements
@SecurityRequirement(name = ACCESS_TOKEN)
public class CommentController {

private final CommentService commentService;

@PostMapping("/{post_id}/comments")
public ResponseEntity<?> createComment(
Principal principal,
@PathVariable("post_id") Long postId,
@Valid @RequestBody CommentCreateRequest commentCreateRequest
) {

CommentCreateResponse commentCreateResponse = commentService.createComment(
principal.getName(), postId, commentCreateRequest);
return ResponseEntity.ok().body(commentCreateResponse);
}

@PatchMapping("/{post_id}/comments/{comment_id}")
public ResponseEntity<?> updateComment(
Principal principal,
@PathVariable("post_id") Long postId,
@PathVariable("comment_id") Long commentId,
@Valid @RequestBody CommentUpdateRequest commentUpdateRequest
) {

CommentUpdateResponse commentUpdateResponse = commentService.updateComment(
principal.getName(), postId, commentId, commentUpdateRequest
);
return ResponseEntity.ok().body(commentUpdateResponse);
}

@DeleteMapping("/{post_id}/comments/{comment_id}")
public ResponseEntity<?> deleteCommentById(
Principal principal,
@PathVariable("post_id") Long postId,
@PathVariable("comment_id") Long commentId
) {

CommentDeleteResponse commentDeleteResponse = commentService.deleteCommentById(principal.getName(), postId, commentId);
return ResponseEntity.ok().body(commentDeleteResponse);
}

}
111 changes: 111 additions & 0 deletions src/main/java/com/example/solidconnection/comment/domain/Comment.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package com.example.solidconnection.comment.domain;

import com.example.solidconnection.entity.common.BaseEntity;
import com.example.solidconnection.post.domain.Post;
import com.example.solidconnection.siteuser.domain.SiteUser;
import jakarta.persistence.*;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@EqualsAndHashCode(of = "id")
public class Comment extends BaseEntity {

// for recursive query
@Transient
private int level;

@Transient
private String path;

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

@Column(length = 255)
private String content;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private Post post;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "site_user_id")
private SiteUser siteUser;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private Comment parentComment;

@OneToMany(mappedBy = "parentComment", cascade = CascadeType.ALL)
private List<Comment> commentList = new ArrayList<>();

public Comment(String content) {
this.content = content;
}

public void setParentCommentAndPostAndSiteUser(Comment parentComment, Post post, SiteUser siteUser) {

if (this.parentComment != null) {
this.parentComment.getCommentList().remove(this);
}
this.parentComment = parentComment;
parentComment.getCommentList().add(this);
Comment on lines +55 to +59
Copy link
Collaborator

@nayonsoso nayonsoso Aug 13, 2024

Choose a reason for hiding this comment

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

[진짜 몰라서 하는 질문] 이렇게 remove 하고 add 하는 부분이 왜 필요한가요? 😲

Copy link
Member Author

Choose a reason for hiding this comment

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

데이터베이스와, 메모리 상태의 일관성을 유지하기 위해 사용하였습니다.

간단한 예시입니다.
기댓값은 1이지만, 0이 출력됩니다.

void test(){
		User user = new User();
		user.setId(1L);
		user.setName("test");

		Post post = new Post();
		post.setId(1L);
		post.setUser(user);

		List<Post> postList = user.getPostList();
		System.out.println("postList.size() = " + postList.size());
	}

remove의 경우, 연관관계상 둘 이상에 포함될 수 없어서 사용하였습니다.

추천키워드: jpa 연관관계 편의 메소드

Copy link
Collaborator

@nayonsoso nayonsoso Aug 17, 2024

Choose a reason for hiding this comment

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

아하!
기존의 연관 관계를 끊기 위해서군요 ㅎㅎ 이해 되었습니다~


if (this.post != null) {
this.post.getCommentList().remove(this);
}
this.post = post;
post.getCommentList().add(this);

if (this.siteUser != null) {
this.siteUser.getCommentList().remove(this);
}
this.siteUser = siteUser;
siteUser.getCommentList().add(this);
}

public void setPostAndSiteUser(Post post, SiteUser siteUser) {

if (this.post != null) {
this.post.getCommentList().remove(this);
}
this.post = post;
post.getCommentList().add(this);

if (this.siteUser != null) {
this.siteUser.getCommentList().remove(this);
}
this.siteUser = siteUser;
siteUser.getCommentList().add(this);
}

public void resetPostAndSiteUserAndParentComment() {
if (this.post != null) {
this.post.getCommentList().remove(this);
this.post = null;
}
if (this.siteUser != null) {
this.siteUser.getCommentList().remove(this);
this.siteUser = null;
}
if (this.parentComment != null) {
this.parentComment.getCommentList().remove(this);
this.parentComment = null;
}
}

public void updateContent(String content) {
this.content = content;
}

public void deprecateComment() {
this.content = null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.example.solidconnection.comment.dto;

import com.example.solidconnection.comment.domain.Comment;
import com.example.solidconnection.post.domain.Post;
import com.example.solidconnection.siteuser.domain.SiteUser;
import jakarta.annotation.Nullable;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Getter;

@Getter
public class CommentCreateRequest {

@NotBlank(message = "댓글 내용은 빈 값일 수 없습니다.")
@Size(min = 1, max = 255, message = "댓글 내용은 최소 1자 이상, 최대 255자 이하여야 합니다.")
String content;

@Nullable
Long parentId;

public CommentCreateRequest(String content, @Nullable Long parentId) {
this.content = content;
this.parentId = parentId;
}

public Comment toEntity(SiteUser siteUser, Post post, Comment parentComment) {

Comment comment = new Comment(
this.content
);

if (parentComment == null) {
comment.setPostAndSiteUser(post, siteUser);
} else {
comment.setParentCommentAndPostAndSiteUser(parentComment, post, siteUser);
}
return comment;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.solidconnection.comment.dto;

import com.example.solidconnection.comment.domain.Comment;

public record CommentCreateResponse(
Long id
) {

public static CommentCreateResponse from(Comment comment) {
return new CommentCreateResponse(
comment.getId()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.example.solidconnection.comment.dto;

public record CommentDeleteResponse(
Long id
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.example.solidconnection.comment.dto;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;

public record CommentUpdateRequest(
@NotBlank(message = "댓글 내용은 빈 값일 수 없습니다.")
@Size(min = 1, max = 255, message = "댓글 내용은 최소 1자 이상, 최대 255자 이하여야 합니다.")
String content
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.solidconnection.comment.dto;

import com.example.solidconnection.comment.domain.Comment;

public record CommentUpdateResponse(
Long id
) {

public static CommentUpdateResponse from(Comment comment) {
return new CommentUpdateResponse(
comment.getId()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.example.solidconnection.comment.dto;

import com.example.solidconnection.entity.Comment;
import com.example.solidconnection.comment.domain.Comment;
import com.example.solidconnection.siteuser.dto.PostFindSiteUserResponse;

import java.time.LocalDateTime;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.example.solidconnection.comment.repository;

import com.example.solidconnection.entity.Comment;
import com.example.solidconnection.comment.domain.Comment;
import com.example.solidconnection.custom.exception.CustomException;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

import static com.example.solidconnection.custom.exception.ErrorCode.INVALID_COMMENT_ID;
public interface CommentRepository extends JpaRepository<Comment, Long> {

@Query(value = """
Expand All @@ -30,4 +32,8 @@ WITH RECURSIVE CommentTree AS (
""", nativeQuery = true)
List<Comment> findCommentTreeByPostId(@Param("postId") Long postId);

default Comment getById(Long id) {
return findById(id)
.orElseThrow(() -> new CustomException(INVALID_COMMENT_ID));
}
}
Loading