[JPA] 양방향 연관관계(1)

Done is better than perfect·2021년 10월 11일
0

JPA

목록 보기
9/12
post-thumbnail

이전 글에서는 비교적 간단한(?) 단방향 연관관계에 대해 정리해보았다. 이번 글에서는 정~말로 더 중요하고 헷갈리는 양방향 연관관계에 대해 알아보고자 한다.

일단 이전과 동일한 시나리오를 다시 살펴보자.

- 회원과 팀이 있다.
- 회원은 하나의 팀에만 소속될 수 있다.
- 회원과 팀은 다대일 관계이다.

이를 단방향 연관관계로 설계했을 때 불편한 점(?)이 한가지 있다.
(불편하지 않을 수도 있다. 로직에 따라 굳이 양방향으로 설계 할 필요가 없을 수 도 있다.)

Member findMember = em.find(Member.class, member.getId());

Team findTeam = findMember.getTeam();			// 가능
List<Member> findMembers = findTeam.getMember();	// 불가능

Member에서 Team은 찾을 수 있지만, Team에서 Member는 찾을 수 없다. 당연하다.
JPA를 떠나 JAVA 코드만 살펴봐도 Member 클래스엔 Team 참조값을 가질 수 있는 필드와 Getter 메소드가 있지만, Team 클래스엔 Member와 관련된 필드와 아무것도 없다. (Member와 Team 클래스는 이전 글 참조)


그렇다면 양방향 연관관계를 만들기 위해선 어떻게 해야할까?

먼저 위 그림에서 테이블 연관관계를 먼저 살펴보자.
전혀 바뀐것이 없다. 그도 그럴것이 테이블은 애초에 단방향, 양방향과 같은 관계가 없다.
외래키로 조인을 통해 내가 얻고싶은 데이터를 얻을 수 있으니 테이블 연관관계는 차이가 없다.

하지만 객체 연관관계는 위의 설명한 것처럼 Team으로부터 Member를 얻기 위해선 Team 클래스에서도 Member 객체를 담을 수 있는 List같은(또는 배열이든 뭐든) 필드가 필요하다.

위 처럼 Member 객체를 가질 수 있는 List형 필드를 추가하고 TEAM의 입장에선 MEMBER는 일대다의 관계이므로 @OneToMany 어노테이션을 추가한다.

클래스를 이렇게 설계하고나면 또 한가지 딜레마가 발생한다.

만약, Member가 속한 Team을 변경하고 싶다면? Member 객체의 team을 변경했을 때 MEMBER 테이블의 FK를 변경해야될까? 또는 Team 객체의 members가 변경됐을 때 MEMBER 테이블의 FK를 변경해야될까? 기준이 필요해보이지 않는가?

그래서 FK를 관리할 기준을 JPA에서는 [연관관계의 주인] 이라고 표현한다.
연관관계의 주인(Owner)은 몇가지 규칙이 있다.

- 객체의 두 관계 중 하나를 연관관계의 주인으로 지정
- 연관관계의 주인만이 외래키를 관리(등록, 수정)
- 주인이 아닌쪽은 읽기만 가능
- 주인은 mappedBy 속성 사용 X
- 주인이 아니면 mappedBy 속성으로 주인 지정

그렇다면 누구를 주인으로 해야할까?

외래키가 있는 곳을 주인으로 정해라

즉, 위의 예제에선 외래키를 갖고 있는 Member.team이 연관관계의 주인이 되는 것이다.
(MEMBER 테이블이 외래키를 갖고 있기 때문이다.)

만약 Team.members를 연관관계의 주인으로 한다면 아래와 같은 애매함이 발생한다. Team 객체의 members를 수정하면? 실질적으로 SQL문은 MEMBER 테이블을 대상으로 발생하기 때문에 직관적이지 못하다. (추가로 성능문제도 있다고 하는데 이 부분은 조금 더 학습해봐야 알것같다.)

결론! 외래키가 있는 곳을 주인으로 정하면 된다.
다시 말하면, 외래키가 있는 곳은 DB입장에선 항상 N, 외래키가 없는곳이 1 관계가 되므로 즉 N:1 관계에서 N쪽을 연관관계의 주인으로 정하면 된다!

다음 포스트에선 양방향 연관관계를 설정할 때 주의할 점에 대해 정리해보자~

0개의 댓글