Published on

다양한 연관 관계 매핑

Authors
  • avatar
    Name
    ywj9811
    Twitter

다양한 연관 관계 매핑

다중성

  • 다대일 : @ManyToOne
  • 일대다 : @OneToMany
  • 일대일 : @OneToOne
  • 다대다 : @ManyToMany

단방향, 양방향

테이블

  • 외래 키 하나로 양쪽 조인 가능
  • 방향의 개념이 없음

객체

  • 참조용 필드가 있는 쪽으로만 참조 가능
  • 한쪽만 참조하면 단방향
  • 양쪽이 서로 참조하면 양방향

연관 관계의 주인

테이블의 경우 외래 키 하나로 두 테이블이 연관 관계를 가질 수 있다.

하지만 객체에서는 A → B, B → A 처럼 참조를 2군데 에서 해야 양방향 관계를 가질 수 있다.

따라서 객체에서 양방향 관계를 가지기 위해서는 둘 중 하나에서 테이블의 외래 키를 관리해야 한다.

이 관리하는 객체를 연관 관계의 주인이라고 한다.

주인의 반대편 : 외래 키를 관리하지 않는 테이블로 단순 조회만 가능하다.

이렇게 3가지의 개념을 유의하고 앞으로 나오는 내용들을 살펴보도록 하자.

다대일[N : 1] 단방향

association

다대일 단뱡향은 가장 많이 사용되는 연관 관계이다.

이렇게 Member 여러개가 하나의 Team에 들어갈 수 있는 것이다.

다대일[N : 1] 양방향

association

이는 다대일 양방향으로 객체 연관 관계가 달라지게 된다.

객체가 서로 연관 관계를 가지기 위해서는 Member여러개가 Team에 소속되니 Member에서 Team을 참조하고 있더라도 Team 객체 내부에 Member를 List로 가져 각각의 Member를 참조할 수 있어야 한다.

이 때 외래 키가 있는 쪽이 연관 관계의 주인이다.(Member)

일대다 단방향 [1 : N]

association

이는 다대일과 비슷하게 이해하면 되는데, 단순하게 생각하면 다대일 관계를 거꾸로 뒤집은 것이다.

일대다 단방향에서는 N : 1 에서 1 부분이 연관 관계의 주인이 된다. 하지만, N이 외래키를 가지고 있다.

이는 테이블과 객체의 연관 관계에서의 차이 때문에 생기는 특이한 구조인 것이다.

연관 관계 주인의 반대 테이블이 외래 키를 관리하는 구조

즉, 무조건 @JoiinColumn을 사용해야 한다.

⚠️ 하지만 번거로움이 생기고, 쿼리문도 추가로 발생하기 때문에 N : 1 양방향을 사용하도록 하자.

일대다 양방향 [1 : N]

이는 공식적으로 존재하지 않는 매핑이다.

사용하기 위해서는 @JoinColumn(insertable=false, updatable=false) 이를 추가해서 사용할 수는 있다.

다만 이보다는 N : 1 양방향 관계를 사용하도록 하자.

일대일 [1 : 1] 단방향

일대일 관계는 그 반대도 일대일이기에 주 테이블, 대상 테이블 둘 중에 외래 키를 선택할 수 있다.

그리고 일대일 관계이기 때문에 외래 키에 데이터베이스 유니크(UNI) 제약 조건 추가한다.

association

위와 같이 연관 관계를 가져가게 되는데, 다대일 단방향 매핑과 거의 유사하다고 볼 수 있다.

일대일 [1:1] 양방향

association

이때도 외래 키가 있는 곳이 연관 관계의 주인이고, 반대편의 경우 mappedBy 속성을 사용해서 하면 된다.

일대일 대상 테이블에 외래키를 넣는 경우

이때는 단방향 지원을 하지 않는다.

양방향만 지원을 하지만 이는 사실상 연관 관계의 주인 외래 키의 양방향과 다른 것이 없다.

다대다 [N : M]

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

따라서 중간에 연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야 한다.

(중간 테이블이 추가되어야 함)

@ManyToMany 를 사용하며 @JoinTable 로 연결 테이블을 지정한다.

물론 객체의 경우는 컬렉션을 사용해서 객체 2개로 다대다 처리가 가능하기는 하다.

association

이는 편리해 보일지 몰라도 단점이 많기 때문에 실무에서 사용하지 않는다.

다대다 한계 극복

다대다 연관 관계를 사용하기 위해서는 연결 테이블이 추가되어야 한다고 했는데, 이 때 연결 테이블을 사용하는 것이 아닌 연결 테이블의 역할까지 수행할 수 있는 엔티티를 추가하는 것이다.

association

즉, @ManyToMany → @OneToMany, @ManyToOne 으로 만들어서 사용하는 것이다.


참고

@JoinColumn 주요 속성

외래 키를 매핑할 때 사용하는 것

속성설명기본 값
name매핑할 외래키 이름필드명 + _ + 창조하는 테이블의 기본 키 컬럼명
referencedColumnName참조하는 테이블의 기본 키 컬럼명
foreignKey

| unique nullable insertable updatable columnDefinition table | | |


@ManyToOne 주요 속성

속성설명기본 값
optionalfalse로 설정하면 연관된 데이터가 항상 존재해야 하도록TRUE
fetch글로벌 페치 전략 설정FetchType.EAGER
cascade영속성 전이 기능 사용
targetEntity연관된 엔티티 타입 정보를 설정
이 기능은 거의 사용하지 않음

@OneToMany 주요 속성

속성설명기본 값
mappedBy연관 관계의 주인 필드를 선택한다.
fetch글로벌 페치 전략 설정FetchType.LAZY
cascade영속성 전이 기능 사용
targetEntity연관된 엔티티 타입 정보를 설정
이 기능은 거의 사용하지 않음