ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 양방향 연관관계와 CASECADE 옵션
    spring/JPA 2021. 2. 25. 00:56

    프로젝트를 진행하던 중 게시글 입력 규칙을 바꾸기로 했다. 기존 게시글은 본인의 이력을 입력하는 필드가 있었는데 이 입력 필드의 개수는 2개로 고정되어 있었다. 요구사항이 변경돼 사용자는 입력 필드를 동적으로 추가하거나 삭제할 수 있게 했다.

     

    변경된 요구사항을 반영하기 위해 JPA와 RDB의 설계를 수정했다. 우선, RDB에서는 간단하게 동적 필드를 테이블로 분리했다. 분리한 테이블은 고유ID를 갖고 게시글의 ID를 FK로 갖는다. 다음으로 JPA 수정에 들어 갔다. 게시글과 이력의 관계는 1:N관계 즉, 한 게시글은 N개의 이력을 갖는다.

     

    JPA에서 1:N관계를 설계할 때 고려해야할 2가지 사항이 있다.

    첫째는 연관관계를 단방향으로 가질지 양방향으로 가질지를 결정해야 한다.

     

    대부분의 객체는 단방향으로 연관관계를 맺으면 충분하다. 예를 들어, 멤버와 게시글의 관계를 생각해보자. 한 멤버는 여러 게시글을 쓸 수 있으니 1:N관계로 풀 수 있다. 이때 멤버의 정보를 이용해서 게시글을 찾는 상황이 흔한 일일까? 멤버를 조회할 때 멤버의ID를 이용해 게시글을 찾아올 상황이 있을까? 마이페이지에서 내가 쓴 게시글 보기와 같은 용도로 가능은 하겠지만 그건 그때 필요한 쿼리를 날리면 그만이다.

     

    다만, 지금 이 요구사항에서는 양방향 연관관계가 필요해보인다. 해당 게시글을 조회할 때 그 게시글이 포함한 이력은 반드시 같이 조회되어야 한다. 이력만 따로 조회할 일은 없다. 또한 게시글을 등록할 때 이력 또한 같이 등록되어야 한다. 이력의 생명주기는 게시글에 100% 의존한다.

     

    이점을 생각해보면 @OneToMany에서 CASECADE옵션을 적용해줘도 될 것 같다. 게시글이 생성될 때 양방향 연관관계를 이용해 List에 이력을 넣어두기만 하면 따로 persist할 필요가 없다. 또한 게시글이 삭제된 경우 당연히 이력 필드도 무의미해진다. 같이 삭제되어야 한다.

     

    여기서 주의해야할 점이 있다. CASECADE옵션과 연관관계주인의 개념은 다르다는 것이다. CASECADE는 생명주기 정도로 이해하면 될 것 같다. 반면, 양방향 연관관계에서 @OneTo*(mappedBy = FK)를 지정해줌으로써 연관관계 주인을 설정하는 건 FK의 관리를 완전히 맡기고 엔티티와 대응하는 테이블은 FK를 생성하지않겠다는 의미다.

     

    CASECADE하고 헷갈리는 부분이다. 다만, CASECADE는 1관계에 있는 칼럼이 생성되거나 삭제될 때 같이 반영되는 옵션이고, 그 이외에서 N관계의 수정, 삭제, 생성을 1관계 칼럼이 관여할 수 없다는 뜻이다.

     

     

    마치며...

    사실 JPA에서 위 개념은 적용하는 게 그리 어렵지 않다.(이해했다면) 변경된 요구사항을 적용하는 데 하루종일을 썼는데, 대부분 시간을 쏟은 건 프런드엔드에서 동적 모달만들기와 spring에서 다중파일 및 텍스트를dto에 예쁘게 잘 받는 부분이었다. 나중에 servlet의 파라미터리졸버도 자세히 공부해야겠다...^^

    'spring > JPA' 카테고리의 다른 글

    연관관계 주인 mappedBy 끝내기  (0) 2021.05.05
    JPA 다른 모듈에서 ENTITY 스캔하기  (0) 2021.04.29
    JPA open session in view 설정하기  (0) 2021.04.08
    JPA와 하이버네이트 N+1 최적화 과정  (0) 2021.04.08
    JOIN FETCH와 JOIN  (0) 2021.03.02

    댓글

Designed by Tistory.