SELF JOIN으로 대댓글 구현

Ango·2023년 7월 11일

SPRING

목록 보기
13/13

❓ 문제점

대댓글 기능을 구현하려고 했는데 대댓글 entity부터 해서 다만들자니 대댓글에 또 댓글이 달리는 부분을 해결할 수 없다는 생각이 들었다.
그래서 다른 방법을 찾아 보았다.

🔑 시도 && 해결 방법

Entity


@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class Comment extends Timestamped {
    // ...


    //셀프 조인
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parentId")
    private Comment parent;

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


    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "postId", nullable = false)
    private Post post;


    public Comment(CommentRequest request,Comment parentcomment) {
        this.content = request.getContent();
        this.parent = parentcomment;
        this.post = parentcomment.getPost();
    }

    // ... 
}

대댓글 기능을 구현하기 위해서 자기 자신과 연관관계를 맺는 self join을 활용해보았다. 특별한 매서드가 필요한건 아니고 말그대로 대댓글과 댓글을
1:N 관계라고 생각하고 연관관계를 맺어주면 된다.

댓글이 삭제되면 해당 대댓글들이 모두 삭제되게 하기위해 CascadeType.ALL 속성을 추가했다.

Controller

@PostMapping("/reply/{commentId}")
    public ResponseEntity<CommentResponse> createComment_Comment(@RequestBody CommentRequest commentRequest,
                                                @PathVariable("commentId") Long commentId,
                                                @AuthenticationPrincipal UserDetailsImpl userDetails) {
        CommentResponse commentResponse = commentService.createComment_Comment(commentRequest, commentId, userDetails.getUser());
        return new ResponseEntity<>(commentResponse, HttpStatus.OK);
    }

댓글의 id를 pathvariable 방식으로 받고 대댓글을 생성하는
createComment_Comment 매서드를 호출해준다.

Service

public CommentResponse createComment_Comment(CommentRequest commentRequest, Long commentId, User user) {
        Comment parentcomment = commentRepository.findById(commentId).orElseThrow(() ->
                new CustomException(ErrorCode.WRONG_COMMENT_ID)
        );

        Comment comment_comment = new Comment(commentRequest, parentcomment);

        commentRepository.save(comment_comment);

        return new CommentResponse(comment_comment);
    }

존재하는 댓글인지 판별해주고 대댓글의 parentId 즉 대댓글이 작성된 댓글의 정보를 생성자를 통해 저장해준다. 그리고 CommentResponse 로 반환한다.

ResponseDto

@Getter
public class CommentResponse {
    String content;

    List<CommentResponse> commentResponseList = new ArrayList<>();

    public CommentResponse(Comment comment) {
        this.content = comment.getContent();

        for(Comment comment_comment : comment.getCommentList()){
            commentResponseList.add(new CommentResponse(comment_comment));
        }
    }
}

해당 조회한 댓글의 대댓글들을 list에 담아서 댓글을 조회할때 해당 댓글의 대댓글들을 모두 조회 할 수 있도록 구현했다.

💡 알게 된 점

자기 자신을 연관관계로 정의해서 구현할 수 있다는 사실을 알 수 있었다.
역시 방법은 다 존재한다..

profile
웹 벡엔드 개발자가 되어보자!

0개의 댓글