* 연관관계 매핑시 고려사항 3가지
1. 다중성 : 다대일 , 일대다 , 일대일 , 다대다
2. 단방향 / 양방향 : 테이블 - 외래키 하나로 양쪽 조인 가능 ( 방향 개념 X )
3. 연관관계 주인 = 외래키(FK) 를 가지고 있는 엔티티
연관관계 주인이 먼저 등장
* 다대일 (N : 1)
▶ 가장 많이 사용 ◀
※ 연관관계 주인은 '다(N)' 이다.
※ 실선 화살표 : 값 입력이 가능한 연관관계 / 점선 화살표 : 조회만 가능한 연관관계
(주) Member -> (종) Team 으로의 단방향 연관관계가 메인이다.
양방향 연관관계를 위해 (종)Team -> (주)Member 로의 연관관계를 추가 한다고 해서 테이블 구성이 달라지지 않는다.
( (종)Team -> (주)Member 연관관계는 조회 전용이기 때문이다. )
* 일대다 (1 : N)
▶ 권장하는 방법 X , 표준 스펙으로 지원은 함. ◀
※ 연관관계 주인은 '일(1)' 이다.
일대다 (1 : N) 양방향 연관관계 매핑을 성립 시키기 위해선, 다음과 같은 방식을 사용해야 한다.
(주)Team은 연관관계 주인이기 때문에 @JoinColumn을 사용하여 외래키(FK)인 "TEAN_ID" 컬럼을 설정한다.
(주)Team -> (종)Member 단방향 연관관계 매핑 완료!
(종)Member는 연관관계에서 '종' 이기 때문에 'mappedBy' 를 이용하여야 하지만, @ManyToOne은 이를 지원하지 않는다.
따라서, 옵션 변경을 통해 인위적으로 만들어 줘야 한다.
@JoinColumn의 INSERT 허용 여부 (insertable) 과 UPDATE 허용 여부 (updatable)을 '불허(false)' 로 바꾸어 조회만 가능하도록 설정한다.
(종)Member -> (주)Team 단방향 연관관계 매핑 완료!
=> (주)Team - (종)Member 양뱡향 연관관계 매핑 완료!
일대다(1 : N) 를 권장하지 않는 이유
"1. 외래키가 (주)TEAM이 아닌 (종)MEMBER 테이블에 존재" 한다.
이로 인해 연관관계 주인인 Team을 통해 값을 입력하는 경우 아래와 같다.
1. INSERT MEMBER 쿼리
2. INSERT TEAM 쿼리
3. UPDATE MEMBER 쿼리
와 같이 상당히 부자연스러운 모습을 볼 수 있다.
이 처럼 "2. 추가 UPDATE SQL 실행" 이 일어난다.
이와 같이 복잡한 방식을 사용하면, 유지보수 측면에도 좋지 않다.
<해결방법>
'일대다(1 : N)'를 쓰는 대신 '다대일(N : M)'을 사용하여 양방향 매핑을 추가하는 방식을 사용하도록 한다.
* 일대일 (1: 1)
▶ 사용해도 됨. ◀
※ 연관관계 주인은 '일(1)' 이다.
일대일 관계는 반대로 해도 일대일 이니까 '주 테이블' 과 '대상 테이블' 중 외래키를 아무데나 넣어도 된다.
※ 외래키 위치 설정 기준
자주 호출되는 엔티티를 외래키 위치로 설정한다.
비즈니스의 대부분 작업에서 Member를 호출하기 때문에,
Member에서 외래키를 갖는 것이 좋다.(상황에 따라 판단)
'다대일 (N : M)' 단방향 매핑과 유사하다.
※ 다대일 방향 매핑 처럼 외래키가 있는 곳이 연관관계의 주인 반대편은 mappedBy 적용
(주)Member - (종)Locker의 양방향 연결관계의 모습이다.
* 다대다 (N : M)
▶ 실무에서 사용하면 안됨. ◀
※ 연관관계 주인은 '다(N)' 이다.
1. 다대다 (N : M)를 구현하는 방법
* RDB는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.
따라서, 별도의 연결 테이블을 추가해서 "일대다", "다대일" 관계로 풀어내야 한다.
[MEMBER] 와 [PRODUCT] 사이에 연결테이블 [MEMBER_PRODUCT]을 활용하여 다대다(N : M) 연관관계를 표현한다.
JOIN TABLE을 JPA가 자동으로 만들어 준다.
2. 다대다 (N : M)을 실무에서 사용하면 안되는 이유
1. 연결테이블이 단순히 연결만 하고 끝나지 않는다.
- 연결 테이블에 필연적으로 추가 데이터가 있어야 한다.
- 그러나 연결테이블에 추가 데이터를 넣는게 불가능하다.
2. 예상피 못한 쿼리가 나간다.
- 중간 테이블의 쿼리가 발생해서 나중에 디버깅(유지보수)가 힘듦
3. 다대다 (N : M) 한계 극복 방법 (다대다 대체 방법)
" '다대다'를 '일대다' , '다대일' 관계로 바꾼다. " + "중간 연결테이블을 엔티티로 승격"
이때, 중간 연결테이블의 PK는 MEMBER_ID, PRODUCT_ID 와 같이 다른 테이블의 PK를 활용하는것이 아닌, 전혀 영향없는 ID로 만들어야 한다.
'Spring > JPA' 카테고리의 다른 글
[JPA - 9] 프록시 (Proxy) (0) | 2023.12.05 |
---|---|
[JPA - 8] 상속관계 매핑 / @MappedSuperclass (0) | 2023.12.02 |
[JPA - 6] 연관관계 매핑 (양방향 연관관계 / 연관관계의 주인 - 중점) (0) | 2023.11.26 |
[JPA - 5] Entity Mapping (0) | 2023.11.25 |
[JPA - 4] 영속성 컨텍스트 (Persistence Context) - 내부 동작 방식 (0) | 2023.11.24 |