[JPA 기본] 6. 다양한 연관관계 매핑
연관관계 매핑시 고려사항 3가지
1. 다중성
예) ManyToOne, OneToMany, OneToOne, ManyToMany
2. 단방향인지 양방향인지
3. 연관관계의 주인
다중성
- 주의: ManyToMany는 실무에서 쓰면 안된다.
- ManyToOne, OneToMany를 주로 쓰며, OneToOne은 가끔 나온다.
양방향 vs 단방향
- 테이블은 외래 키 하나로 양쪽 조인 한다. 따라서 방향이라는 개념이 없다.
- 반면 객체는 참조용 필드로 참조 가능. 따라서 방향 개념 존재 (양방향, 단방향)
연관 관계의 주인
객체 2개가 양방향 관계를 맺을 때, 둘 중 테이블의 외래키를 관리할 곳을 찾아야 함.
- 주인 : 외래 키를 관리
- 주인 반대편: 외래 키 영향 x. 단순 조회만 가능.
1. 다대일
'Many'가 주인
다대일 단방향
- 가장 많이 사용하는 연관관계.
- e.g.Member-Team의 관계에서 Member가 Many. 따라서 Member의 team이 주인이다.
다대일 양방향.
- Member만 Team을 포함하고, Team은 멤버를 조회할 수 없는 것이 기존의 '다대일 단방향' 연관관계. '다대일 양방향 관계'에서는 이 때, Team이 members를 포함하여도 테이블에는 영향을 끼치지 않는 것이 핵심.
2. 일대다
- 정의: 1:다 관계에서 일(1)이 연관관계의 주인 (예. Team.members가 주인)
- 사용예시: Teeam은 members를 알고 싶은데, member에서는 Team에 대한 정보가 필요 없을 때
- 주의: 테이블에선 무조건 Many에 외래키 들어간다.
- 주의: @JoinColumn을 꼭 사용하자. 그렇지 않으면 조인 테이블 방식이 사용됨. (중간에 테이블 하나 추가)
- 권장되는 모델링 방법은 아님. (실무에서 거의 안 씀)
2.1 일대다의 단점
- 엔티티의 외래키가 다른 테이블에 있다. (meber에 외래키 있는데, Team이 주인을 가지면 헷갈림)
- 연관관계 관리 위해 update 쿼리 추가 실행 (member insert, team insert, member update)
- team만 손댄 것 같은데, member도 업데이트 된다. (운영시 헷갈림)
2.2 결론
권장되는 전략 : 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자.
2.3 참고: 일대다 양방향
- JPA 스펙에서 공식적으로 존재하지 않는다. 꼼수를 아래처럼 쓸 수는 있다.
- @JoinColumn(insertable=false, updatable=false)를 통해 읽기 전용 필드 생성.
- 일대다 양방향은 쓰지말자.. 다대일 양방향을 사용하자...
3. 일대일 (1:1)
- 주 테이블(=주로 엑세스하는 테이블)과 대상 테이블 중 외래키 넣을 곳 선택 가능
- 실무에서 강사님은 주테이블에 FK를 넣음. (Member 뒤진 다음 Locker 뒤질 필요 x) >> DBA와 협의 필요.
- 외래 키에 데이터 베이스 유니크 제약 조건 추가
( 유니크 제약 조건 없으면 한 쪽이 Many가 될 수 있으므로 꼭 필요)
- 예) Member - Locker 관계 (1명에게 사물함 한 개 배정)
- 일대일 단방향, 일대일 양방향
주의!!!!
** 일대일 대상테이블에 외래키 단방향은 불가능. ('일대일' 강의 7:11)
** 대상 테이블에 외래키 양방향은 가능. ('일대일' 강의 14:19)
-> 일대일 정리 PPT 정리 상세 내용 참고할것. (외래키를 주테이블 / 대상 테이블에 둘 경우에 대해 장단점 나옴)
4. 다대다
- 실무에서 절대로 쓰면 안된다.
- 관계형 데이터 베이스는 정규화된 테이블 2개로 다대다 관계 표현 불가능. 연결 테이블 통해 일대다, 다대일 관계로 풀어냄.
: 예) Member - Member_Product - Product
- 다:다의 한계 어떻게 극복할까?
-> 연결 테이블용 엔티티 추가(연결 테이블을 엔티티로 승격)
-> 강의 10:32
- Member_Product 테이블에서 Member_ID와 Product_ID를 함께 사용하여 Composite Primary key로 사용하는 경우도 있다. 하지만 유연성을 위해 composite PK보다는 의미 없는 값 (예. auto generated value) 하나를 PK로 쓰자. (다:다 강의 12:58)