연관관계 매핑시 고려사항 3가지
다중성
- 다대일:
@ManyToOne
- 일대다:
@OneToMany
- 일대일:
@OneToOne
- 다대다:
@ManToMany
- 다대다는 절대 실무에서 사용하면 안 된다.
단방향, 양방향
테이블
- 외래키 하나로 양쪽 조인이 가능하다.
- 따라서, 방향의 개념이 없기 때문에 항상 양방향이다.
객체
- 참조용 필드가 있는 쪽으로만 참조가 가능하다.
- 한쪽만 참조하면 단방향, 양쪽이 서로 참조하면 양방향이다.
- 양방향도 사실 단방향이 2개 있는 것이지만, 논리적으로 양방향으로 취급한다.
연관관계의 주인
- 테이블은 외래키 하나로 두 테이블이 연관 관계를 맺는데, 객체는 그렇게 하지 모 한다.
- 따라서 양방향인 경우, 두 참조에서 어느 값을 업데이트할 때 외래키에 적용할지 설정해야 하는데, 이것이 주인이다.
다대일
다대일 단방향
![](https://blog.kakaocdn.net/dn/b7bZrz/btsjRV55U0S/vqX1OuMtiB3AvpzKSJkamK/img.png)
- 가장 많이 쓰는 연관관계다.
다대일 양방향
![](https://blog.kakaocdn.net/dn/dUmJ7C/btsjS42M9fk/yPfLRIMXj9fK4I3Ky8kh9K/img.png)
- 외래키가 있는 쪽(다)이 연관관계의 주인이다.
- 미러(주인이 아닌 쪽)에서 로직상 참조를 많이 해야하는 경우에 이렇게 양방향으로 설정한다.
일대다
일대다 단방향
![](https://blog.kakaocdn.net/dn/cqu48X/btsjRWYeXZR/eDfIho3H2KlizBH3ZoJTVk/img.png)
- 멤버 입장에서는 Team이 궁금하지 않은 경우에 사용한다
- 불필요해 보이지만, 객체 입장에서는 이런 설계가 나올 가능성이 있긴하다.
- 다만, DB설계상 무조건 다인 Member쪽에 FK가 있어야하므로
Team
의members
가 변경되면 Member의 TEAM_ID가 변경되도록 매핑시켜 주어야한다.- Tema Entity를 건드려도 Member테이블이 변경되기 때문에 디버깅시 추적이 매우 까다롭다.
- 따라서, 이럴 경우에는 그냥 다대일 양방향으로 만들어 버리는게 맞다.
- 혹시나 일대다 단방향으로 설계하는 경우에,
@JoinColumn
을 반드시 사용해야한다.- 만약 사용하지 않으면,
JoinTable
방식을 default로 사용하기 때문에 중간 table이 생겨버린다.
- 만약 사용하지 않으면,
일대다 양방향
![](https://blog.kakaocdn.net/dn/eXf2NV/btsjKS4tO46/qfxE3lZB1lYSxY8v48DyhK/img.png)
- 이런 매핑은 공식적으로 존재하지 않는다..! 그러니 생각도 하지말고, 그냥 다대일 양방향을 사용하자.
- 일대다 단방향에서 Member쪽에서는 읽기 전용 매핑(
@JoinColumn(insertable=false, updatable=false
)을 사용해서 주먹구구식으로 구현할 수는 있다.
- 일대다 단방향에서 Member쪽에서는 읽기 전용 매핑(
일대일
- 일대일은 그 반대도 일대일관계다. 따라서 주 테이블, 대상 테이블 모두 외래키를 넣을 수 있다.
- 일대일 = 다대일 + DB에서 유니크 제약조건
💡
“DB에서 유니크 제약조건”이란?
테이블 전체에서 유니크해야 한다는 조건을 붙히는 것이다. 즉, FK가 유니크해 지므로 “다”쪽에 제약이 걸려 “일대일”이 되어버리는 것이다.
일대일 단방향
![](https://blog.kakaocdn.net/dn/cA5a9Z/btsjO3xlCzt/4a9zZNYYEIXe1gkP1MZJN1/img.png)
- Locker에 MEMBER_ID(FK)를 넣어도 된다. 둘 다 일대일 관계다.
- 다대일 단방향과 같은 방식으로 매핑한다.
@OneToOne @JoinColumn(name = "LOCKER_ID") private Locker locker;
일대일 단방향(대상 테이블에 외래키) ⇒ JPA로 구현 불가
![](https://blog.kakaocdn.net/dn/bNh44r/btsjPEYhmf3/SCIFVukpz21IZHJ8CbAS1K/img.png)
일대일 양방향
![](https://blog.kakaocdn.net/dn/B0mji/btsjILR0lsU/4aTH0Lb6cxYff1YAlIImY0/img.png)
- 다대일 양방향과 동일하다. 반대편에는 mappedBy를 적용하자.
@OneToOne(mappedBy = "locker") private Member member;
- 다대일 처럼 FK가 있는 곳이 주인이 된다.
일대일 양방향(대상 테이블에 외래키)
![](https://blog.kakaocdn.net/dn/dU2bB6/btsjOo23U5M/Lc75cYZoiZjBFMpKb57T40/img.png)
- 그저 주인이 바뀐것이므로 문제없다.
일대일 정리
- 주 테이블에 외래키
- 객체지향 개발자가 선호한다.
- JPA 매핑이 편리하다.
- 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 없는지 확인 가능하다.
- 단점: 값이 없으면 외래키에 null을 허용해야한다.
- 대상 테이블에 외래키
- DBA들이 서노한다.
- 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조를 유지할 수 있다.
- 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩된다.
다대다
![](https://blog.kakaocdn.net/dn/bn8Cu9/btsjOo23U6C/7EBIkCd2MkVepXs8y3ADU0/img.png)
- 관계형 DB는 다대다 관계를 표현할 수 없으므로, 중간 테이블을 생성하여 다대일 - 일대다 형식으로 풀어내야한다.
- 그런데, 객체는 다대다가 가능하다. 서로 List를 가지면 된다. 따라서, 아래와 같은 그림을 JPA가 지원해주어야한다.
![](https://blog.kakaocdn.net/dn/bCMQkm/btsjJTvr5SA/MICSJKvqGK09BFv5B8NgG0/img.png)
@ManyToMany
를 사용하고,@JoinTable
을 사용해서 연결 지정이 가능하다.- 다만, 실무에서 이렇게 사용하면 안 된다.
- 이렇게 사용하면 단순히 연결 Table을 만들고 다른 Column을 넣을 수가 없다. 주문시간, 수량 같은 데이터를 넣을 수 없으므로 실무에선 사용이 불가능하다.
- 쿼리도 중간 테이블로 쿼리가 나가므로, 다른 테이블을 조회하는 것 처럼 보여 디버깅이 힘들다.
Uploaded by N2T
(23.06.12 10:35)에 작성된 글 입니다.