Backend

[JPA] 다양한 연관관계 매핑(다대일, 일대일, 다대다)

연_우리 2022. 2. 21. 16:23
반응형

목차

     

     

    다대일 / N:1 / @ManyToOne / N이 주인인 경우

    외래키가 있는 쪽이 주인

    N이 주인 : @ManyToOne, @JoinColumn(name = "~")

    (양방향인 경우) 1이 서브 : @OneToMany(mappedBy = "~")

     

     

     

    일대다 / 1:N / @OneToMany / 1이 주인인 경우

    외래키가 있는 쪽이 주인...이어야하는데

    객체와 테이블의 차이 때문에 반대편 테이블의 외래키를 관리하는 특이한 구조

    1이 주인 : @OneToMany, @JoinColumn(name = "~")

    (양방향인 경우) N이 서브 : @ManyToOne, @JoinColumn(name = "~", insertable = false, updatable = false) (사용하지말자)

     

    단점! 

     - 엔티티가 관리하는 외래 키가 다른 테이블에 있다.

     - 연관관계 관리를 위해 추가로 Update SQL이 실행된다.

        ( team.getMembers().add(member) => Member테이블의 team_id를 수정해주어야함.. )

     - 일대다 단방향매핑보다 다대일 양방향매핑을 사용하자

     

     

     

    일대일 / 1:1 / @OneToOne / 주인 선택 가능

    주 테이블, 대상 테이블 중 아무거나 주인으로 선택해도 상관없다.

    외래키에 데이터베이스 UNIQUE 제약조건을 추가하자.

     

    외래키가 있는 쪽이 주인

    주인 : @OneToOne, @JoinColumn(name = "~")

    (양방향인 경우) 서브 : @OneToOne(mappedBy = "~")

     

    참고!

    Member테이블에 locker_id를 추가해도, Locker테이블에 member_id를 추가해도 상관없이 1대1 관계는 성립한다.

    현재는 Member가 1개의 Locker를 가질 수 있지만, 나중에 Member가 N개의 Locker를 가지게된다면??

    => 이때는 Unique제약조건 하나만 빼면 성립할 수 있게 Locker에 member_id가 추가되는 것이 좋다. (대상 테이블에 외래키 존재)

     

    하지만 객체 입장에서는 Member안에 Locker가 있는 편이, getLocker해서 로직 구성하기가 더 쉽다. (주 테이블에 외래키 존재)

    어디를 "주"로 하고 어디에 "외래키"를 넣을지 결정은 각자의 몫이다!

     

     

     

    다대다 / N:M / @ManyToMany / 사용하지말자...

    관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다

     

    하지만 객체는 컬렉션을 사용해서 다대다 관계를 표현할 수 있다

    둘중에 하나 선택해서 주인으로 만든다.

    주인 : @ManyToMany, @JoinTable(name = "~")

    (양방향인 경우) 서브 : @ManyToMany(mappedBy = "~")

    @JoinTable(name = "category_item",
            joinColumns = @JoinColumn(name="category_id"),
            inverseJoinColumns = @JoinColumn(name="item_id")
    )

     

    다대다 매핑의 한계

     - 연결 테이블이 단순히 연결만 하고 끝나지 않는다. 

        회원과 상품인 경우 상품을 주문하게되면 수량도 필요하고, 언제 주문했는지도 정보로 있어야한다.

        회원_상품 테이블에는 주문시간, 수량 같은 데이터가 더 추가될 수 있다

     - 객체는 2개지만 테이블은 연결테이블까지 3개이다. 

        객체로는 보이지 않는 연결 테이블이 중간에 숨어있기 때문에 내가 생각하지 못한 쿼리가 나갈 수 있다.

        차라리 연결 테이블을 엔티티로 승격시켜서 눈에 보이게 처리하는 것이 좋다.

     

     

    ⭐연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야한다.

     

     

     

    반응형
    • 네이버 블러그 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 구글 플러스 공유하기
    • 카카오톡 공유하기