| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- Spring
- JPA
- CORS
- @ComponentScan
- JWT
- docker compose
- docker
- 지연 로딩
- 스프링 부트
- @Transactional
- Routing Key
- kafka
- DLQ
- 서블릿 컨테이너
- 쿠버네티스
- Spring Data JPA
- Spring Container
- JPQL
- redis
- mybatis
- securitycontextholderfilter
- 컨테이너
- dockerhub
- JdbcTemplate
- Web
- MSA
- Dead Letter Queue
- DI
- 페이징
- AWS
- Today
- Total
look-forest
다양한 연관 관계 매핑 본문
연관관계 관련 이슈

다중성과 방향
다대일 [N:1] - 외래 키가 있는 N쪽이 주인인 케이스

: 다에서 FK를 관리하는 경우
- 가장 많이 사용한다.
- 다대일 양방향
- 양쪽을 서로 참조하도록 개발
- 외래 키가 있는 쪽이 연관관계의 주인
- 양쪽 데이터 싱크를 맞춰야하고(양방향 편의 메서드 쓰자), 결합도가 높아지니 가급적 쓰지말자.
일대다 [1:N] - 예상치 못한 update문을 쓰지 않도록 사용 지양
일대다 단반향 예

- 객체와 테이블의 차이 때문에 반대편 테이블의 외래 키를 관리하는 특이한 구조
객체는 TEAM에서 @OneToMany로 MEMBER를 참조하는데, 실제 테이블은 MEMBER에 FK가 있다. - @JoinColumn을 꼭 사용해야 함(하지만 FK는 항상 다 쪽에 있으므로 update문은 다른 테이블에 나간다).
그렇지 않으면 조인 테이블 방식을 사용함(중간에 테이블을 하나 추가함) - 엔티티가 관리하는 외래 키가 다른 테이블에 있음
- 연관관계 관리를 위해 추가로 UPDATE SQL 실행하는 등 쿼리를 예측하기 어렵다.
- TEAM 엔티티를 INSERT했는데 MEMBER 테이블에 외래키 UPDATE문도 나가서 혼란스럽게 된다.
- TEAM에서 영속성 전파로 MEMBER까지 CASCADE로 PERSIST될 경우, 아래와 같이 처리된다.
=> INSERT TEM, INSERT MEBER, UPDATE MEMBER SET TEAM_ID = ? WHERE ID=?
JPA 입장에선 MEMBER 객체에 없는 FK의 정보를 모르기 때문에, 일단 각각 처리하고 후처리.
1) TEAM을 INSERT
2) CASCADE하라니 MEBER를 INSERT해야 하는데, MEMBER 엔티티엔 FK에 대한 컬럼이 없다.
3) 일단 MEMBER를 INSERT하고 TEAM_ID를 찾아 업데이트한다.
객체 상 TEAM에서 MEMBER를 참조하고 싶겠지만.. 어쩔 수 없이 테이블 기준으로 맞추는 게 낫다.
일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자. (N이 주인, 1은 조회만)
일대일 [1:1] - 어느쪽이 주인이 되어도 되니까, 이왕이면 객체지향적으로 메인 쪽에!
주 테이블(주로 사용)이나 대상 테이블 중에 아무거나 외래 키 선택 가능. (DBA와 협의 필요)
외래 키에 데이터베이스 유니크(UNI) 제약조건 추가
[ case 1 - 주 테이블에 외래 키 단방향(양방향도 가능) ]

- 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
- 단점: 값이 없으면 외래 키에 null 허용
[ case 2 - 대상 테이블에 외래 키 양방향 (단방향 관계는 JPA 지원X) ]

- 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지 (member가 여러 locker)
- 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨
어차피 Member에서 Locker 조회 시 Locker 테이블에 데이터가 있는지 봐야하므로. null로 처리할지 프록시를 넣을지.
(FK를 모를 경우, 프록시를 만드려면 NULL인지 아닌지를 알아야하므로 상태 테이블에서 조회해봐야한다.)
다대다 [N:M] - 필드 추가X, 엔티티 테이블 불일치로 사용하지 마라
관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다. (어느쪽에 FK를 두든 PK가 중복된다)
연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야한다.
반면 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계 가능하다.

JPA에서는 @ManyToMany와 @JoinTable로 연결 테이블 지정하여 위 관계를 자동으로 생성해준다.
그러나 편리해 보이지만 실무에선 사용하면 안된다.
연결 테이블이 눈에 보이지 않아 관리되지도 않고, FK외 다른 컬럼을 추가할 수 없어 실용적이지 않다.
따라서 직접 연결 테이블용 엔티티 추가하면 된다.(연결 테이블을 엔티티로 승격)
@ManyToMany -> @OneToMany, @ManyToOne



참고 자료 & 이미지 출처
자바 ORM 표준 JPA 프로그래밍 - 기본편 (김영한 님)
'JPA > JPA' 카테고리의 다른 글
| 프록시와 연관관계 관리 (3) | 2024.09.10 |
|---|---|
| 고급 매핑 (0) | 2024.09.10 |
| 연관관계 매핑 기초 (1) | 2024.09.09 |
| 엔티티 매핑 (1) | 2024.09.08 |
| 영속성 관리 - 내부 동작 방식 (0) | 2024.09.08 |