TIL(Today Ingwang Learned)

TIL)2022-12-17(Spring)

김코식 2022. 12. 20. 00:16

 


Spring boot 

대댓글 구현

1. 구현 고민

  • 댓글 처럼 대댓글도 레포지토리를 만들어 따로 저장을 할것인가
  • 댓글을 부모 댓글(댓글) 과 자식 댓글(대댓글) 로 나누어 저장하여 사용할 것인가

결과 - 대댓글을 따로 만들어 관리하면 관리할 부분이 많아지고 유지보수 하기 어려워짐 > 2번안으로 결정

 

2. 구현

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


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;                // 댓글 번호

    @Column(nullable = false)
    private String nickname;        // 작성자명

    @Column(nullable = false)
    private String contents;        // 작성내용

    @ManyToOne(fetch = FetchType.LAZY)
    @JsonIgnore
    @JoinColumn(name = "userid", nullable = false)
    private User user;              // 작성자 id

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "productid", nullable = false)
    @JsonIgnore
    private Product product;        // 게시판 id

    @Column(nullable = false)
    private int depth;             // 대댓글 확인용

    @ManyToOne(fetch = FetchType.LAZY)
    @JsonIgnore
    @JoinColumn(name = "parentid")
    private Comment parent;         // 부모 댓글

    @Builder.Default
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "parent", orphanRemoval = true)
    private List<Comment> children = new ArrayList<>();  // 대댓글 리스트

Comment entity에서

Comment parent(부모댓글)를 ManyToOne으로 연관관계를 맺고

대댓글리스틀를 OneToMany로 연관관계를 맺음

 

댓글을 저장할 때 저장하는 댓글이 자식 댓글인지 부모 댓글인지 확인 후 저장

@Transactional
public CommentResponseDto createcomment(Long id, Long comment_id, CommentRequestDto requestDto, User user) {
    // 게시글 DB에서 입력받은 id값으로 일치하는 데이터 proudct 객체에 저장
    Product product = productRepository.findById(id).orElseThrow(
            () -> new CustomException(PRODUCT_NOT_FOUND)
    );

    // 댓글 DB에서 입력받은 게시글과 댓글id로 조회해서 일치하는 값 parent_commet 객체에 저장
    Comment comment;
    if (comment_id == 0) {
        comment = commentRepository.save(new Comment(requestDto, user.getNickname(), product, user));
    } else {
        Comment childComment = commentRepository.findById(comment_id).orElseThrow(
                () -> new CustomException(COMMENT_NOT_FOUND)
        );
        if (commentRepository.findByProductAndId(product, comment_id).isEmpty()){
            throw new CustomException(COMMENT_NOT_FOUND);
        }
        comment = commentRepository.save(new Comment(requestDto, user.getNickname(), product, user, childComment));
    }
    return new CommentResponseDto(comment, comment_id);
}

 

 게시글을 출력할 때 부모댓글과 자식 댓글을 판단하여 부모 댓글 안에 자식 댓글이 들어가도록 설계

public ProductResponseDto getProduct(Long id) {

    Product product = productRepository.findById(id).orElseThrow(
            () -> new CustomException(PRODUCT_NOT_FOUND)
    );
    List<CommentResponseDto> commentResponseDtoList = new ArrayList<>();
    for (Comment comment : product.getCommentList()) {
        List<CommentResponseDto> childCommentList = new ArrayList<>();
        if(comment.getParent()==null){                                                      //부모 댓글이 없을 경우
            for (Comment childComment : comment.getChildren()){                              //자식 댓글 리스트의 데이터를 childComment에 저장
                if (id.equals(childComment.getProduct().getId())) {                         //childComment의 id와 받아온 id가 일치할 경우(선택 게시글 저장)
                    childCommentList.add(new CommentResponseDto(childComment));             //저장된 자식댓글을 리스트에 저장
                }
            }
            commentResponseDtoList.add(new CommentResponseDto(comment,childCommentList));   //저장된 데이터를 리스트에
        }
    }

 

대댓글 구현 완료~