Search
Duplicate
📒

[JPA 기본] 06-1. 다양한 연관관계 맵핑

상태
완료
수업
JPA
주제
JPA
4 more properties
참고

연관관계 매핑시 고려사항 3가지

NOTE

다중성

다대일 : @ManyToOne
일대다 : @OneToMany
일대일 : @OneToOne
다대다 : @ManyToMany
다대다는 실무에서 사용하지 않는게 좋다!

단방향, 양방향

테이블
외래키 하나로 양쪽 join가능
방향이라는 개념이 없음
객체
참조형 필드가 있는 쪽으로만 참조가능
한 쪽만 참조하면 단방향
양쪽이 서로 참조하면 양방향

연관관계의 주인

테이블은 외래 키 하나로 두 테이블의 연관관계를 맺음
객체 양방향 관계는, A B가 아닌, A B, B A처럼 참조가 2곳임

@ManyToOne - 다대일(N:1)

NOTE
객체 양방향 관계에서 연관관계의 주인은 항상 다 (Many)쪽이다.
ex) 회원(Many)과 팀(One)이 있다면 회원 쪽이 연관관계의 주인이다.

주요속성

속성
설명
기본값
mappedBy
연관 관계의 주인 필드를 선택한다.
TRUE
fetch
글로벌 패치 전략 설정
@ManyToOne = FetchType.EAGER @OneToMany = FetchType.LAZY
cacade
영속성 전이 기능을 사용한다.
targetEntity
연관된 엔티티의 타입 정보를 설정한다. (거의 사용안함)

@ManyToOne - 단방향

NOTE
Member → Team 참조
가장 많이 사용하는 연관관계

@ManyToOne - 양방향

NOTE
Member와 Team이 서로 참조함
외래 키가 있는 쪽(Many)연관관계의 주인이다.
연관관계의 주인이 아닌 쪽은, 단순 조회만 가능하기에 필드만 추가해주면 된다.
@OneToMany private List<Member> members = new ArrayList<>();
Java
복사

@OneToMany - 일대다(1:N)

NOTE
일(One)연관관계의 주인이다.
권장하는 방법이 아니다. (실무에서도 거의 사용되지 않음)

권장하지 않는 이유

NOTE
1.
테이블에서는 항상 다(Many)쪽에 외래키가 있기 떄문에 패러다임 충돌이 존재한다.
2.
실무에서 테이블이 수십개 이상 운영이 되는데, 관리 및 트레이싱이 어렵다.
Ex) 일대다(1:N)에서 저장이 될 때 양 쪽 객체를 저장한 뒤 update query를 통해 외래키를 설정해야한다. (3번이나 수행)

결론

기본은 단방향 다대일(N:1)로 구현하고 필요에 의해 양방향 다대일(N:1)관계를 수립하자.

@OneToMany - 단방향

NOTE
Team.members의 값에 따라 Member의 FK가 관리가되는 구조
테이블의 일대다 관계는 항상 다(Many)쪽에 외래 키가 있다
객체와 테이블의 차이 떄문에 반대편 테이블의 외래키를 관리하게 됨.

@ManyToOne - 양방향

NOTE
이런 매핑은 공식적으로 존재하지 않지만, 설정을 통해서 구현은 할 수 있다.
/* 팀(Team) */ public class Team{ ... @OneToMany @JoinColumn(name="TEAM_ID") private List<Member> members = new ArrayList<>(); ... }
Java
복사
/* 멤버(Member) */ public class Member{ ... @ManyToOne @JoinColumn(name="TEAM_ID", insertable=false, updatable=false) private Team team; ...
Java
복사
양쪽다 주인이 되지만, Member 생성 수정이 불가능해지게 만들었다.

@OneToOne- 일대일(1:1)

NOTE
일대일 관계주 테이블이나 대상 테이블누가 외래 키를 가질지 선택해야 한다.

주 테이블에 왜래키

주 테이블외래키를 두고 대상 테이블을 참조한다.
주 테이블에서 대상 테이블과의 연관관계 처리가 쉽다.

대상 테이블에 외래 키

대상 테이블외래키를 두고 주 테이블을 참조한다.
테이블 관계를 일대일 → 일대다로 변경할 떄 테이블 구조를 그대로 유지할 수 있다.

@OneToOne- 단방향

NOTE

외래 키 - 주 테이블

@Entity public class Member { // ... @OneToOne @JoinColumn(name = "LOCKER_ID") private Locker locker; }
Java
복사
일대일 단방향 관계 코드

외래 키 - 대상 테이블 (지원안함)

JPA에서 대상 테이블에 FK가 있는 일대일 단방향 관계는 지원하지 않는다

@OneToOne- 양방향

NOTE
어떤 테이블에 FK를 두는지 차이가 있을 뿐 동일하다

외래 키 - 주 테이블

@Entity public class Member { // ... @OneToOne @JoinColumn(name = "LOCKER_ID") private Locker locker; }
Java
복사
주인
@Entity public class Locker { // ... @OneToOne(mappedBy = "locker") private Member member; }
Java
복사

외래 키 - 대상 테이블

@Entity public class Member { // ... @OneToOne(mappedBy = "member") private Locker locker; }
Java
복사
@Entity public class Locker { // ... @OneToOne @JoinColumn(name = "MEMBER_ID") private Member member; }
Java
복사
주인

@ManyToMany 다대다(N:N)

NOTE
관계형 데이터베이스정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.
그래서 보통 다대다 관계일대다, 다대일 관계로 풀어내는 연결 테이블을 사용한다.
@JoinTable로 연결 테이블 지정

@ManyToMany - 문제점

NOTE
연결 테이블을 자동으로 생성해주는 방식이 편해보이지만, 실무에서 안쓴다.
연결 테이블이 단순히 연결만 하는게 아니라, 다른 데이터도 포함되기 떄문이다.
@JoinTable로 생성하면, 테이블의 FK만 받아서 생성된다.
추가적인 데이터를 넣지 못함
중간 테이블이 숨겨져 있기 때문에, 의도치 않은 쿼리가 발생할 수도 있다.

@ManyToMany - 문제점 해결(연결 Entity 사용)

NOTE
연결 테이블용 Entity를 추가해준다. (연결 테이블을 엔티티로 승격)
@ManyToMany@OneToMany, @ManyToOne
[ 참고]
연결 테이블용 Entity에서 각 FK를 복합키 PK 선언도 가능하지만, 새로운 PK를 생성해주는 것이 좋다.