CS/자바 ORM 표준 JPA 프로그래밍
[JPA] 연관관계 매핑
jisu0708
2024. 1. 7. 17:32
해당 포스트는 김영한 님의 [자바 ORM 표준 JPA 프로그래밍] 을 읽고 정리한 글입니다.
1. 단방향 연관관계
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
private int age;
//@Column(name = "TEAM_ID")
//private Long teamId;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
→ 현재 상황에서 Team에서 member 접근은 불가
2. 양방향 매핑
테이블의 연관관계는 바뀌지 않은 채 양방향 객체 연관관계를 만든다.
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
private int age;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<Member>()
...
}
- Team 엔티티에 컬렉션을 추가
양방향 매핑 (반대 방향으로 객체 그래프 탐색)
//조회
Team findTeam = em.find(Team.class, team.getId());
int memberSize = findTeam.getMembers().size(); //역방향 조회
3. 연관관계의 주인과 mappedBy
1) 객체와 테이블이 관계를 맺는 차이
객체 연관관계 = 2개
- 회원 -> 팀 연관관계 1개(단방향)
- 팀 -> 회원 연관관계 1개(단방향)
테이블 연관관계 = 1개
- 회원 <-> 팀의 연관관계 1개(양방향)
→ 객체의 양방향 관계는 서로 다른 단방향 관계 2개다.
→ 테이블은 외래 키 하나(MEMBER.TEAM_ID)로 두 테이블의 연관관계를 관리한다.
2) 연관관계의 주인 (Owner)
양방향 매핑 규칙
- 연관관계의 주인만이 외래 키를 관리 (등록, 수정) → 외래 키가 있는 곳이 주인
- 주인이 아닌 쪽은 읽기만 가능
- 주인이 아니면 mappedBy 속성으로 주인 지정
→ 양방향 매핑시 연관관계의 주인에 값을 입력해야 한다. (member.setTeam(team);)
→ 순수한 객체 관계를 고려하면 항상 양쪽 다 값을 입력해야 한다.
단방향 매핑만으로도 이미 연관관계는 매핑 완료되었다. 양방향 매핑은 반대 방향으로 조회가 가능하게 한다.
4. 다대일 (N:1)
1) 다대일 단방향
- 가장 많이 사용하는 연관관계
- 다대일의 반대는 일대다
2) 다대일 양방향
- 외래 키가 있는 쪽이 연관관계의 주인
- 양쪽을 서로 참조하도록 개발
5. 일대다 (1:N) → 권장 X
- 일대다 단방향은 일대다(1:N)에서 일(1)이 연관관계의 주인
- 테이블 일대다 관계는 항상 다(N) 쪽에 외래 키가 있음
- 객체와 테이블의 차이 때문에 반대편 테이블의 외래 키를 관리하는 특이한 구조
- @JoinColumn을 꼭 사용해야 함. 그렇지 않으면 조인 테이블 방식을 사용함(중간에 테이블을 하나 추가함)
→ 하지만 일대다 단방향 매핑의 경우, 외래 키가 다른 테이블에 있어 연관관계 관리를 위해 추가로 UPDATE SQL을 실행해야 한다.
→ 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자!
(일대다 양방향 매핑은 공식적으로 존재 X)
6. 일대일 (1:1)
1) 주 테이블에 외래 키 단방향
- 외래 키에 데이터베이스 유니크 제약조건 추가
2) 주 테이블에 외래 키 양방향
- 외래 키가 있는 곳이 연관관계의 주인
- 반대편은 mappedBy 적용
대상 테이블에 외래 키 단방향 관계는 JPA가 지원하지 않는다. 양방향 관계는 지원하는데 이게 결국 주 테이블에 외래 키 양방향…
3) 정리
주 테이블에 외래 키
- 주 객체가 대상 객체의 참조를 가지는 것처럼 주 테이블에 외래 키를 두고 대상 테이블을 찾음
- 객체지향 개발자 선호
- JPA 매핑 편리
- 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
- 단점: 값이 없으면 외래 키에 null 허용
대상 테이블에 외래 키
- 대상 테이블에 외래 키가 존재
- 전통적인 데이터베이스 개발자 선호
- 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
- 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨(프록시는 뒤에서 설명)
7. 다대일 (N:M)
관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없어 연결 테이블을 추가해서 일대다, 다대일 관계로 풀어내야 한다.