오봉이와 함께하는 개발 블로그
JPA - 양방향 연관관계와 연관관계의 주인1 - 기본 본문
양방향 연관관계와 연관관계의 주인1 - 기본
양방향 매핑
전에 했던 코드는 Member에서는 Team을 얻어올 수 있는 관계 즉, 단방햔 매핑 관계였다.
이제 우리는 Member to Team, Team to Member 모두 얻어올 수 있게 양방향 매핑 관계로 구성을 해야 한다.
테이블에서는 외래키로 조인을 하면 되기 때문에 양방향 참조를 할 때는 테이블에 변화가 생기지 않는다.
즉 테이블에서는 외래키 하나로 양방향을 다 알 수 있기 때문에 사실상 방향이 존재하지 않는다.
하지만, 객체는 아니기 때문에 Team에 Member를 넣어줘야 참조할 수 있다.
코드
멤버는 전과 동일하다.
public class Member {
@Id
@GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
// @Column(name = "TEAM_ID")
// private Long teamId;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
public class Team {
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
Member에서는 ManyToOne이기 때문에 Team에서는 OneToMany라고 하면 된다.
mappedBy 옵션에 "team"은 Member 클래스의 team이라는 객체 이름으로 매핑이 되어 있다는 뜻이다.
Member findMember = em.find(Member.class, member.getId());
List<Member> members = findMember.getTeam().getMembers();
for (Member m : members) {
System.out.println("m.getUserName() = " + m.getName());
}
위 코드를 통해 반대 방향으로 객체 그래프 탐색하여 Member에서 Team으로 다시 Team에서 Member를 찾을 수 있게 됐다.
연관관계의 주인과 mappedBy
객체와 테이블간 연관관계를 맺는 차이를 이해해야 한다.
- 객체 연관관계는 2개
- 회원 -> 팀 연관관계 1개(단방향)
- 팀 -> 회원 연관관계 1개(단방향)
- 테이블 연관관계는 1개
- 회원 <-> 팀의 연관관계 1개(양방향)
- TEAM_ID(FK)를 통해 양쪽 값을 모두 알 수 있다.
객체의 양방향 관계
- 객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개다.
- 그래서 객초를 양방향으로 참조하기 위해서는 단방향 연관관계를 2개 만들어야 함.
class A {
B b;
}
class B {
A a;
}
- A -> B (a.getB())
- B -> A (b.getA())
테이블의 양방향 연관관계
- 테이블은 외래키 하나로 두 테이블의 연관관계를 관리함.
- MEMBER.TEAM_ID 외래키 하나로 양방향 연관관계를 가진다
- 양쪽으로 조인할 수 있다.
SELECT *
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
SELECT *
FROM TEAM T
JOIN MEMBER M ON T.TEAM_ID = M.TEAM_ID
객체의 양방향 관계 딜레마
Member to team, Team to members로 가는 참조 값이 있는데, 어떤 걸로 매핑을 해야 할까?
DB에서는 Member 테이블의 TEAM_ID(FK)값만 업데이트 되면 상관없는데
Member의 team 값을 바꿨을 때 외래키가 업데이트 되어야 할까?
Team의 members 값을 바꿨을 때 외래키가 업데이트 되어야 할까?
Member의 team으로 외래키를 관리할지, Team의 members로 외래키를 관리할지 주인을 정해야 한다.
연관관계의 주인(Owner)
- 양방향 매핑 규칙
- 객체의 두 관계중 하나를 연관관계의 주인으로 지정
- 연관관계 주인만이 외래키를 관리(등록, 수정)
- 주인이 아닌 쪽은 읽기만 가능
- 주인은 mappedBy 속성 사용하지 않음
- 주인이 아니면 mappedBy 속성으로 주인 지정
누가 주인이 되어야 할까?
- 외래키가 있는 곳을 주인으로 정하자
- 외래키가 있는 곳을 주인으로 정하면 무조건 N 쪽이 연관관계 주인으로 정해진다.
- 여기서는 Member.team이 연관관계의 주인이 된다.
- 간단하게 @JoinColumn이 있는 쪽이 주인이다.
Team.members를 주인으로 정해서 값을 바꿨다고 예를 들면 Team.members의 값을 바꿨는데 Member테이블의 값이 변경되는 문제가 생긴다.
이는 연관관계를 이해하기 어려울 뿐더러 매우 햇갈리고 성능 이슈도 발생한다.
출처 : 인프런 김영한 지식공유자님의 스프링 부트와 JPA 실무 완전 정복 로드맵 강의
'BE > JPA' 카테고리의 다른 글
JPA - 실전 예제 2 - 연관관계 매핑 (0) | 2022.06.25 |
---|---|
JPA - 양방향 연관관계와 연관관계의 주인 - 주의점, 정리 (0) | 2022.06.25 |
JPA - 단방향 연관관계 (0) | 2022.06.24 |
JPA - 실전 예제 1 - 요구사항 분석과 기본 매핑 (0) | 2022.06.24 |
JPA - 필드와 컬럼 매핑, 기본 키 매핑 (0) | 2022.06.24 |