[01.11] 내일배움캠프[Spring] TIL-51

박상훈·2023년 1월 11일
0

내일배움캠프[TIL]

목록 보기
51/72

[01.11] 내일배움캠프[Spring] TIL-51

1. SQL

Join

//기본 조인 buy 테이블과 member테이블의 mem_id를 통해 겹치는 부분을 뽑아낸다
SELECT * 
from buy b join member m on b.mem_id = m.mem_id;

//공통된 속성으로 조인된 상태에서의 조건절 where를 걸 수 있다.
SELECT * 
from buy b join member m on b.mem_id = m.mem_id
where b.mem_id = "BLK";

//inner join vs outer join
//outer join -> 공통된 속성 뿐만 아니라 LEFT(왼쪽 테이블)의 데이터도 같이 출력되게하는 것이라고 생각하자.
select m.mem_id,m.mem_name,b.prod_name,m.addr
from member m LEFT OUTER JOIN buy b
ON m.mem_id = b.mem_id
ORDER BY m.mem_id;

2. 기존 프로젝트 리펙토링

CASCADE( 유저탈퇴 )

  • 원래는 엔티티별로 연관관계를 설정해줬었는데, 연관관계를 끊어주고 ID의 속성만 들고 있게하여 CASCADE속성을 쓰지 못하게 됐다.
  • 그래서 UserId를 바탕으로 해당 유저가 쓴 게시글, 댓글을 지워주는 방향으로 코드를 작성했다.

UserService

    @Transactional
    public String  delete(User user) {

        String userName = user.getUsername();
        //해당 유저에 관한 모든 정보를 지울 때 여기서 다 호출해서 쓰는게 맞을까 의문.
        userRepository.deleteById(user.getId());

        boardService.deleteAllBoardByUser(user.getId());
        commentService.deleteCommentByUser(user.getId());


//        List<Comment> commentList = commentRepository.findAllByUserId(user.getId())


        return userName+"님이 탈퇴 되셨습니다, 관련 정보는 모두 사라집니다!";

    }
  • UserService라는 비즈니스 로직에 BoardService, CommentService가 DI되어있는게 걸리지만, 현재로써는 이게 최선이다.

대댓글( 연관관계 설정 )

  • 원래 추상적으로 생각했을 때는 게시글 -> 댓글 처럼 대댓글 엔티티를 따로 만들어주려고 했었다.
  • 그렇게 했을 때 뭔가 관리해야할 테이블도 하나 더 생기는 기분이라 기존에 있던 Comment를 활용하면 어떨가 하는 생각이 들었고, 어차피 댓글의 속성을 그대로 가져가니, 그래도 될거라는 생각으로 구글링에 들어갔다.
  • 구글링 결과 대부분 계층형 구조로 연관관계를 지어서 사용하고 있었고, 그 생각을 바탕으로 코드를 작성했다.

Comment Entity

 @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PARENT_ID")
    private Comment parent;

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

  • 처음에 왜 @ManyToOne으로 Comment 타입으로 parent를 선언했을까를 먼저 고민했다.
  • 댓글 < - > 대댓글은 일단 1:N의 관계이다. 그런데 대댓글의 엔티티 입장으로 봤을 때는 댓글과
    @ManyToOne이 된다. 따라서 Parent(원래 댓글)과 대댓글의 관계 = @ManyToOne이 되는게 맞다.
  • @OneToMany로 양방향은 왜 맺어준 것일까?
  • 지난 번 Board < - > Comment를 양방향 맺어준 것 처럼 Board에서 해당 댓글을 모두 가져올 때 편하게 사용하기 위함( 객체 지향적 )이 아닐까 생각은 들지만, 이 때 N+1의 문제가 발생할 수 있다.
  • 만약 대댓글이 1만개인데, comment.getChild()를 하면?? 쿼리 1만1개 다 나가게 되기 때문에!

간단한 에로사항 및 해결

  • Board.getComment()를 사용해서 DTO로 반환했을 때는 Comment가 없어도 NPE가 발생하지 않았지만,
    위와 같은 상황에서는 comment.getChild()를 했을 때는 NPE가 발생했다.
  • 생각해보면 간단했다. -> Board는 게시글이 생성되어 있으므로 Board Entity가 잘 돌아갔고, Board.getComment()가 []로 초기화가 되어 들어갈 수 있기 때문이다.
  • Comment는 Comment가 만들어지지도 않았는데 comment.get~~~를 한다? 모순이다.
package com.sparta.spartagroupsixproject.dto;

import com.sparta.spartagroupsixproject.entity.Comment;
import lombok.Getter;
import lombok.Setter;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Getter
public class CommentResponseDto {

    private Long id;
    private String content;
    private LocalDateTime createdAt;
    private LocalDateTime modifiedAt;
    private Long likenum;

    private List<CommentResponseDto> children = new ArrayList<>();

    public CommentResponseDto(Comment  comment){
        this.id = comment.getId();
        this.content = comment.getContent();
        this.likenum = comment.getLikenum();
        this.createdAt =comment.getCreatedAt();
        this.modifiedAt = comment.getModifiedAt();
        if(comment.getChild()!=null) {
            for (Comment comment1 : comment.getChild()) {

                children.add(new CommentResponseDto(comment1));
            }
        }
    }

}
  • 그래서 일단 null이 아닐 때 comment.getChild()를 할 수 있도록 조건을 걸어서 해결했다.
  • 내일은 양방향 연관관계를 끊고 ID값으로만 작업을 해볼 예정이다 ( N+1 )

3. 코딩 테스트

profile
기록하는 습관

0개의 댓글