06. 다양한 연관관계 매핑
#
연관관계 매핑시 고려사항 3가지- 다중성
- 다대일, 일대다, 일대일, 다대다
- 다대다는 실무에서 거의 쓰면 안됨
- 단방향, 양방향
- 테이블
- 외래 키 하나로 양쪽 조인 가능
- 사실 방향이라는 개념이 없음
- 객체
- 참조용 필드가 있는 쪽으로만 참조 가능
- 한쪽만 참조하면 단방향
- 양쪽이 서로 참조하면 양방향 (필요할때만 추가적으로 구현)
- 단방향 두개
- 테이블
- 연관관계의 주인
- 객체의 양방향 관계는 참조가 각각 두군데
- 둘 중 테이블의 외래키를 관리할 곳을 정해야함
- 외래키가 있는 쪽으로 연관관계 주인을 설정하길 권장
#
다대일 (N:1)@ManyToOne
#
단방향#
양방향#
일대다 (1:N)@OneToMany
- 권장하지 않음
- Team 객체가 MEMBER의 필드를 수정하는 다른 테이블의 데이터를 수정하는 꼴이 발생
- 업데이트 쿼리 하나 더 나가게됨 (성능상 이슈)
#
일대다 단방향- 단점
- 객체와 테이블의 차이때문에 반대편 테이블의 외래키를 관리하는 특이한 구조가 형성됨
- 다른 테이블에 외래키가 있어서 UPDATE 쿼리가 하나더 나감
- 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자
@JoinColumn
을 꼭 사용해야됨, 아니면 조인 테이블을 새로 생성해서 관리하게 됨
#
일대다 양방향- 공식적으로 존재하진 않고
@JoinColumn
에 insertable, updatable 옵션을 false로 설정해서 읽기전용으로 만듦 - 그냥 다대일 양방향 사용하자
#
일대일 (1:1)@OneToOne
- 주 테이블이나 대상 테이블 중에 외래 키 선택 가능
- 외래키에 DB 유니크 제약조건 추가
- 테이블 설계시 유의 사항
- Member, Locker 둘중에 외래키는 어디에 있는게 좋을까?
- 하나의 회원에 여러개의 Locker를 가질 수 있다면?
- Locker에 있는게 유니크 조건만 없애면 가능해짐
- 대신 양방향으로 구현하게 됨
- JPA 사용입장에선 Member에 LOCKER_ID 있는게 개발상 편한게 많음
- 하나의 회원에 여러개의 Locker를 가질 수 있다면?
- Member, Locker 둘중에 외래키는 어디에 있는게 좋을까?
#
일대일 정리- 주 테이블에 외래키
- 장점: 주 테이블만 조회에도 대상 테이블에 데이터가 있는지 확인 가능
- 단점: 값이 없으면 외래키에 null 허용
- 대상 테이블에 외래키
- 장점
- 일대일을 일대다 관계로 변경시 유니크 제약만 없애면 되서 편함
- 단점
- 양방향으로 거의 구현됨
- 프록시 기능의 한계로 지연 로딩이 안되고 즉시 로딩됨 ??
- 쿼리를 해봐야 null인지 아닌지 확인가능하기 때문 (뒤에 설명)
- 장점
#
다대다 (N:M)@ManyToMany
@JoinTable
- 실무에서 쓰면 안됨 -> 편안하게~
#
왜 쓰면 안되는가- RDB는 다대다를 표현할 수가 없음
- 관계형 테이블을 추가해서 일대다, 다대일 관계로 풀어내야함
- 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계 가능
#
한계 극복- 연결 테이블용 객체 추가
- ManyToMany를
- 연결 테이블용엔 ManyToOne
- 대상 테이블엔 OneToMany 로 개선
#
연결 테이블용 만들시 주의사항- FK 복합키와 따로 Id PK 필드를 뺄지 트레이드오프가 있음
- PK로 새로 구성하는게 이후 요구사항 추가 변경 시 편했음~
#
실습 정리- 다대다
- 권장하지 않음
- 다대일
@ManyToOne
은 mappedBy 옵션이 없어 무조건 연관관계 주인이 되어야 한다