[JPA기본] 6. 다양한 연관관계 매핑

kiwonkim·2021년 11월 30일
0

[ 이전 포스팅 ]

연관관계를 클래스에서는 필드에서 다른 객체를 갖도록 해 구현한다. 연관관계에서 매핑시 다중성, 단/양방향, 연관관계 주인을 고려해야 한다.
다중성은 @OneToMany 등으로 설정하며, 방향은 양쪽 클래스 모두에 서로의 객체 필드가 있는지 여부로 결정하고, 연관 관계 주인은 외래키를 관리하는 클래스이다.
연관 관계 주인은 FK를 갖는쪽으로 설정하며 @JoinColumn 으로 FK 명을 입력하고, 반대쪽은 mappedBy 로 필드명을 입력한다.

이번 포스팅에서는 다야항 연관관계에서 다중성, 연관관계 주인등을 어떻게 설정해야 하는지 알아보자


[ 다대일(N:1) ]

가장 많이 사용하는 연관관계. N 쪽이 연관관계의 주인이 된다.

다대일 단방향

  • 다중성 : @ManyToOne
  • 연관관계 주인 : FK 가진 쪽에 @JoinColumn 으로 FK 설정

다대일 양방향

  • 다중성 : FK 가진 쪽 - @ManyToOne, 반대 쪽 - @OneToMany
  • 연관관계 주인 : FK 가진쪽이 연관관계 주인. @ManyToOne 쪽에 @JoinColumn 으로 FK 설정. @OneToMany 쪾은 mappedBy 로 상대 필드 입력.

[ 일대다(1:N) ]

주로 사용하지 않는 연관관계. 1 쪽이 연관관계 주인이 된다. 일대다 대신 다대일을 사용하자.

일대다 단방향

  • 다중성 : @OneToMany
  • 연관관계 주인 : FK 를 갖고 있지 않는 One 쪽에 @JoinColumn 으로 FK 설정

일대다 양방향

  • 다중성 : @OneToMany, @ManyToOne
  • 연관관계 주인 : FK 를 갖고 있지 않은 쪽이 연관관계의 주인이다. @OneToMany 쪽에 @JoinColumn 으로 FK 설정.
  • 한계 : @ManyToOne 어노테이션은 mappedBy 속성을 지원하지 않아, 일대다로 양방향을 수행하려면 읽기 전용 필드를 사용하는 편법을 써야한다.

한계

FK 를 갖고 있지 않은 쪽이 연관관계의 주인이 되는 일대다는 사용하지 말자. @ManyToOne에 mappedBy 속성이 없어 양방향 매핑이 어렵다.
연관관계의 주인은 반드시 FK를 가진 쪽에 두는 다대일 관계를 사용하자.


[ 일대일(1:1) ]

일대일 관계는 주 테이블과 대상 테이블 중 어디에 FK를 둘지 선택이 가능하다.

일대일 단방향

  • 다중성 : @OneToOne
  • 연관관계 주인 : DB 설계에서 FK가 있는 쪽을 연관관계 주인으로 설정. @JoinColumn 추가하자.

일대일 양방향

  • 다중성 : 양쪽에 @OneToOne
  • 연관관계 주인 : DB 설계에서 FK가 있는 쪽이 연관관계 주인. 반대쪽은 mappedBy 속성 설정하자.

DB 설계시 어디에 FK를 둘 것인가

Member 마다 하나의 Locker 를 할당하는 Member-Locker 관계를 보자.

Member 에 외래키

  • 장점: Member 는 조회할 일이 잦음. Member 만 조회해도 Locker 에 데이터가 있는지 없는지 확인 가능.
  • 단점 : 값이 없을 경우 FK에 null이 오게된다.

Locker 에 외래키

  • 장점 : 한명의 Member 가 여러개의 Locker 를 쓰게 되면 FK에 unique 옵션만 해제해주면 되므로 설계의 유연성
  • 단점 : 프록시 기능 한계로 지연로딩 불가.

객체지향 개발자는 주 테이블(Member)에 외래키를 두는 방식을 선호한다.


[ 다대다(N:M) ]

RDBMS 에서는 다대다 관계를 표현할 수 없기에 관계 테이블을 둔다. 하지만 객체에서는 서로 List 객체를 필드로 두며 다대다 관계가 가능하다. 그래서 JPA 는 다대다 관계를 확인하면 자동으로 관계테이블을 생성해준다.

@ManyToMany 사용

  • 다중성 : 양쪽에 @ManyToMany 사용
  • 연관관계 주인 : @JoinTable 어노테이션으로 직접 연결테이블을 생성한다.

다대다 매핑의 한계

다대다 매핑에서는 JPA 가 자동으로 관계테이블을 생성해준다. 그러나 관계 테이블에 컬럼을 추가할 수 있는 방법이 없다.

관계테이블 직접 생성

따라서 관계테이블을 직접 엔티티로 생성하고, 기존 테이블과 @OneToMany @ManyToOne 관계로 맺어서 사용한다. FK 는 관계 테이블이 갖으므로 관계 테이블이 모든 연관관계의 주인이 된다.


[ 결론 ]

1:N 관계는 반드시 FK 를 갖는 테이블이 연관관계의 주인이 되도록 설계하자.
1:1 관계는 테이블 설계시 FK 를 누가 가질지 결정할 수 있다. 결정된 FK 를 갖는 쪽이 연관관계의 주인이 되도록 하자.
N:M 관계는 다대다 매핑을 사용하면 관계테이블 컬럼 추가가 불가능하므로 관계 테이블을 엔티티로 등록해서 사용하자.

0개의 댓글