[JPA-Basic][6] 다양한 연관관계 매핑

kiteB·2021년 10월 14일
0

JPA

목록 보기
6/28
post-thumbnail

[ 연관관계 매핑시 고려사항 3가지 ]

  • 다중성
  • 단방향, 양방향
  • 연관관계의 주인

1. 다중성

  • 다대일: @ManyToOne
  • 일대다: @OneToMany
  • 일대일: @OneToOne
  • 다대다: @ManyToMany (실무에서 사용X)

2. 단방향, 양방향

테이블

외래 키로 연관관계를 맺는다.

  • 외래 키 하나로 양쪽 조인 가능하기 때문에 방향이라는 개념이 없다.

객체

참조(주소)로 연관관계를 맺는다.

  • 참조용 필드가 있는 쪽으로만 참조가 가능하다.
    • 한쪽만 참조하면 단방향
    • 양쪽이 서로 참조하면 양방향 (사실 단방향이 두 개인 것)

3. 연관관계의 주인

  • 테이블은 외래 키 하나로 두 테이블이 연관관계를 맺음
  • 객체 양방향 관계는 A → B, B → A처럼 참조가 두 군데
  • 객체 양방향 관계는 참조가 2군데 있으므로 둘 중 테이블의 외래 키를 관리할 곳을 지정해야 한다.
    • 연관관계의 주인: 외래 키를 관리하는 참조
    • 주인의 반대편: 외래 키에 영향을 주지 않음, 단순 조회만 가능

[ 다대일(N:1) ]

가 연관관계의 주인이다!

1. 다대일 단방향

  • 회원과 팀이 있다.
  • 회원은 하나의 팀에만 소속될 수 있다.
  • 회원과 팀은 다대일 관계다.

  • 가장 많이 사용하는 연관관계
  • 다대일의 반대는 일대다

객체 연관관계

  • 회원 객체는 Member.team 필드로 팀 객체와 연관관계를 맺는다.
  • 회원 객체와 팀 객체는 단방향 관계다. 회원은 Member.team 필드를 통해서 팀을 알 수 있지만, 팀은 회원을 알 수 없다.

테이블 연관관계

  • 회원 테이블은 TEAM_ID 외래 키로 팀 테이블과 연관관계를 맺는다.
  • 회원 테이블과 팀 테이블은 양방향 관계다. 회원 테이블의 TEAM_ID 외래 키를 통해서 회원과 팀을 조인할 수 있고 반대로 팀과 회원도 조인할 수 있다.

객체 연관관계와 테이블 연관관계의 가장 큰 차이

참조를 통한 연관관계는 언제나 단방향이다.


2. 다대일 양방향

  • 외래 키가 있는 쪽이 연관관계의 주인
  • 양쪽을 서로 참조하도록 개발

[ 일대다(1:N) ]

이 연관관계의 주인! (권장하지는 않는다 🙄)

1. 일대다 단방향

  • 객체) Team을 중심으로 외래 키를 관리하고, Member 입장에서는 Team에 대한 참조가 없다.
  • 테이블) 테이블 일대다 관계항상 다(N) 쪽에 외래 키가 있다.
    → 객체와 테이블의 차이 때문에 반대편 테이블의 외래 키를 관리하는 특이한 구조

권장하지 않는 이유 ❗

  • 테이블에서는 항상 다(N) 쪽에 외래 키가 있기 때문에 패러다임 충돌이 발생한다.
  • @JoinColumn을 꼭 사용해야 한다! 아니면 조인 테이블 방식을 사용해야 한다.
  • 실무에서는 테이블이 수십 개 이상 운영되는데, 관리 및 트레이싱이 어렵다.
  • 객체 TeamList members 값을 변경하면 다른 테이블(Member) 속 외래 키 TEAM_ID를 업데이트 해줘야 한다.

📌 일대다 단방향 매핑의 단점

  • 엔티티가 관리하는 외래 키가 다른 테이블에 있음
  • 연관관계 관리를 위해 추가로 UPDATE SQL 실행해야 한다.
    → 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자!

실행 결과


2. 일대다 양방향

  • 이런 매핑은 공식적으로 존재 ❌
  • @JoinColumn(insertable=false, updatable=false)
    • 읽기 전용 필드를 사용해서 양방향처럼 사용하는 방법
    • 이 속성이 없으면 연관관계의 주인이 2개인 것처럼 된다. 😨

→ 그냥 다대일 양방향을 사용하자!


[ 일대일(1:1) ]

  • 일대일 관계는 그 반대도 일대일
  • 주 테이블이나 대상 테이블 중에 외래 키 선택 가능
    • 주 테이블에 외래 키
    • 대상 테이블에 외래 키
  • 외래 키에 데이터베이스 유니크(UNI) 제약조건 추가

1. 주 테이블에 외래 키

단방향

  • 다대일(@ManyToOne) 단방향 매핑과 유사하다.

양방향

  • 다대일 양방향 매핑처럼 외래 키가 있는 곳이 연관관계의 주인
  • 반대편은 mappedBy 적용

2. 대상 테이블에 외래 키

단방향

  • 단방향 관계는 JPA 지원 ❌
  • 양방향 관계는 지원!

양방향

  • 사실 일대일 주 테이블에 외래 키 양방향과 매핑 방법은 같다.

📌 정리

  • 주 테이블에 외래 키
    • 주 객체가 대상 객체의 참조를 가지는 것처럼 주 테이블에 외래 키를 두고 대상 테이블을 찾음
    • 객체지향 개발자 선호
    • JPA 매핑 편리
    • 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
    • 단점: 값이 없으면 외래 키에 null 허용
  • 대상 테이블에 외래 키
    • 대상 테이블에 외래 키가 존재
    • 전통적인 데이터베이스 개발자 선호
    • 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
    • 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨(프록시는 뒤에서 설명)

[ 다대다(N:M) ]

실무에서 사용하지도 않고, 추천하지도 않는 연관관계! 😣


관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없음
연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야 한다.

객체컬렉션을 사용해서 객체 2개로 다대다 관계가 가능!

  • @ManyToMany 사용
  • @JoinTable로 연결 테이블 지정

다대다 매핑도 단방향, 양방향 모두 가능하다!


1. 다대다 매핑의 한계

  • 편리해 보이지만 실무에서 사용 ❌
  • 연결 테이블이 단순히 연결만 하고 끝나는 경우는 없다.
    • 주문 시간, 수량 같은 데이터가 들어올 수 있다.
      → 즉, 다대다 매핑으로 만들어진 중간 테이블에 추가 정보를 넣을 수 없다!
  • 중간 테이블이 숨겨져 있기 때문에 예상치 못한 쿼리가 나간다.

2. 다대다 한계 극복

  • 연결 테이블용 엔티티 추가 (연결 테이블을 엔티티로 승격)
  • @ManyToMany@OneToMany, @ManyToOne
profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글