목차
다대일 / N:1 / @ManyToOne / N이 주인인 경우
외래키가 있는 쪽이 주인
N이 주인 : @ManyToOne, @JoinColumn(name = "~")
(양방향인 경우) 1이 서브 : @OneToMany(mappedBy = "~")
일대다 / 1:N / @OneToMany / 1이 주인인 경우
외래키가 있는 쪽이 주인...이어야하는데
객체와 테이블의 차이 때문에 반대편 테이블의 외래키를 관리하는 특이한 구조
1이 주인 : @OneToMany, @JoinColumn(name = "~")
(양방향인 경우) N이 서브 : @ManyToOne, @JoinColumn(name = "~", insertable = false, updatable = false) (사용하지말자)
단점!
- 엔티티가 관리하는 외래 키가 다른 테이블에 있다.
- 연관관계 관리를 위해 추가로 Update SQL이 실행된다.
( team.getMembers().add(member) => Member테이블의 team_id를 수정해주어야함.. )
- 일대다 단방향매핑보다 다대일 양방향매핑을 사용하자
일대일 / 1:1 / @OneToOne / 주인 선택 가능
주 테이블, 대상 테이블 중 아무거나 주인으로 선택해도 상관없다.
외래키에 데이터베이스 UNIQUE 제약조건을 추가하자.
외래키가 있는 쪽이 주인
주인 : @OneToOne, @JoinColumn(name = "~")
(양방향인 경우) 서브 : @OneToOne(mappedBy = "~")
참고!
Member테이블에 locker_id를 추가해도, Locker테이블에 member_id를 추가해도 상관없이 1대1 관계는 성립한다.
현재는 Member가 1개의 Locker를 가질 수 있지만, 나중에 Member가 N개의 Locker를 가지게된다면??
=> 이때는 Unique제약조건 하나만 빼면 성립할 수 있게 Locker에 member_id가 추가되는 것이 좋다. (대상 테이블에 외래키 존재)
하지만 객체 입장에서는 Member안에 Locker가 있는 편이, getLocker해서 로직 구성하기가 더 쉽다. (주 테이블에 외래키 존재)
어디를 "주"로 하고 어디에 "외래키"를 넣을지 결정은 각자의 몫이다!
다대다 / N:M / @ManyToMany / 사용하지말자...
관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다
하지만 객체는 컬렉션을 사용해서 다대다 관계를 표현할 수 있다
둘중에 하나 선택해서 주인으로 만든다.
주인 : @ManyToMany, @JoinTable(name = "~")
(양방향인 경우) 서브 : @ManyToMany(mappedBy = "~")
@JoinTable(name = "category_item",
joinColumns = @JoinColumn(name="category_id"),
inverseJoinColumns = @JoinColumn(name="item_id")
)
다대다 매핑의 한계
- 연결 테이블이 단순히 연결만 하고 끝나지 않는다.
회원과 상품인 경우 상품을 주문하게되면 수량도 필요하고, 언제 주문했는지도 정보로 있어야한다.
회원_상품 테이블에는 주문시간, 수량 같은 데이터가 더 추가될 수 있다
- 객체는 2개지만 테이블은 연결테이블까지 3개이다.
객체로는 보이지 않는 연결 테이블이 중간에 숨어있기 때문에 내가 생각하지 못한 쿼리가 나갈 수 있다.
차라리 연결 테이블을 엔티티로 승격시켜서 눈에 보이게 처리하는 것이 좋다.
⭐연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야한다.
'Backend' 카테고리의 다른 글
[JPA] 프록시와 즉시로딩, 지연로딩 / 영속성 전이와 고아객체 (0) | 2022.02.21 |
---|---|
[JPA] 상속관계 매핑, 공통 속성 매핑 (0) | 2022.02.21 |
[JPA]영속성 관리 : 내부 동작 방식 (0) | 2022.02.21 |
[JPA] 연관관계 매핑 (0) | 2022.02.20 |
[OAuth2] 동작과정 (0) | 2022.02.05 |