twocowsong

연관관계의 주인 본문

IT/JPA

연관관계의 주인

WsCode 2022. 6. 4. 18:33

엄밀히 이야기하면 객체에는 양방향 연관관계라는것이 없습니다.

서로다른 단방향 연관관계 2개를 애플리케이션 로직으로 잘 묶어서 양방향인 것처럼 보이게 할 뿐입니다.

반면에 DB테이블은 외래키 하나로 양쪽이 서로 조인을 할 수 있습니다.

 

객체 연관관계는 다음과 같습니다.

-회원 : 팀 연관관계 1개 (단방향)

-팀 : 회원 연관관계 1개 (단방향)

 

테이블 연관관계는 다음과 같습니다.

- 회원  < -- > 팀의 연관관계 1개 (양방향)

 

테이블은 외래 키 하나로 두 테이블의 연관관계를 관리합니다.엔티티를 단방향으로 매핑하면 참조를 하나만 사용하므로 이 참조로 외래키를 관리하면 됩니다.그런데 양방향으로 매핑하면 회원 -> 팀 , 팀 -> 회원 두곳에서 서로를 참조하게됩니다.

따라서 객체의 관리하는 포인트는 2곳으로 늘어나게됩니다.

 

엔티티를 양방향 연관관계로 설정하면 객체의 참조는 둘인데 외래 키는 하나입니다.

따라서 둘 사이에 차이가 발생합니다.

그렇다면 둘 중 어떤 관계를 사용해서 외래키를 관리를해야할까요?

 

이런 차이로 인해 JPA에서는 두 객체 연관관계 중 하나를 정해서 테이블의 외래키를 관리해야 하는데 이것을 연관관계의 주인이라 합니다.

 


- 연관관계의 주인

양방향 연관관계 매핑 시 지켜야할 규칙이 있는데 두 연관관계중 하나를 연관관계의 주인으로 정해야합니다.

연관관계의 주인만이 DB 연관관계와 매핑되고 외래키를 관리(등록, 수정, 삭제)할 수 있습니다.

반면에 주인이 아닌 쪽은 읽기만 할 수 있습니다.

 

어떤 연관관계를 주인으로 정할지는 mappedBy 속성을 사용하면 됩니다.

- 주인은 mappedBy속성을 사용하지 않습니다.

- 주인이 아니면 mappedBy속성을 사용해서 속성의 값으로 연관관계의 주인을 지정해야 합니다.

// 회원 -> 팀 (Member.team) 방향
public class Member {
   @ManyToOne
   @JoinColumn(name = "TEAM_ID")
   private Team team;
}

// 팀 -> 회원(Team.members) 방향
class Team {
   @OneToMany
   private List<Member> members = new ArrayList<>();
}

연관관계의 주인을 정한다는 것은 사실 외래 키 관리자를 선택하는 것입니다.

회원 테이블에 있는 TEAM_ID 외래 키를 관리할 관리자를 선택해야 합니다.

만약 회원 엔티티에 있는 Member.team을 주인으로 선택하면 자기 테이블에 있는 외래키를 관리하면 됩니다.

하지만 팀 엔티티에 있는 Team.members를 주인으로 선택하면 물리적으로 전혀 다른 테이블의 외래키를 관리해야합니다.

 

위의 경우에는 Team.members가 있는 Team 엔티티는 TEAM테이블에 매핑되어 있는데 관리해야할 외래 키는 MEMBER 테이블에 있기 때문입니다.

 

- 연관관계의 주인은 외래 키가 있는 곳

연관관계의 주인은 테이블에 외래 키가 있는곳으로 정해야 합니다.

여기서는 회원 테이블이 외래키를 가지고있으므로 Member.team이 주인이 됩니다.

주인이 아닌 Team.members에는 mappedBy = "team" 속성을 사용해서 주인이 아님을 설정해야합니다.

그리고 mappedBy 속성의 값으로는 연관관계의 주인인 team을 주면됩니다.

여기서 mappedBy의 값으로 사용된 team은 연관관계의 주인인 Member 엔티티의 team필드를 말합니다.

 

 

정리하면 연관관계의 주인만 DB 연관관계와 매핑되고 외래 키를 관리할 수 있습니다.

연관관계의 주인은 외래 키가 있는곳입니다.

주인이 아닌 반대편은 읽기만 가능하고 외래키를 변경하지 못합니다.

 

아래와같이 Team을 조회하여 외래키 변경이 불가능합니다.

Member엔티티가 이미 참조하고있기때문이라고 생각합니다.

public static void test2(EntityManager em) {
   Team team = em.find(Team.class, "team1");
   team.setId("team1-1");
}

DB 테이블의 1 : N , N : 1 관계에서는 항상 N 쪽이 외래 키를 가집니다.

@ManyToOne은 항상 연관관계의 주인이 되므로 mappedBy를 설정 할 수 없습니다.

따라서 @ManyToOne에는 mappedBy 속성이 없습니다.

 

 

 

'IT > JPA' 카테고리의 다른 글

양방향 연관관계의 주의점  (0) 2022.06.06
양방향 연관관계 저장  (0) 2022.06.05
양방향 연관관계 매핑  (0) 2022.06.03
양방향 연관관계  (0) 2022.06.01
연관된 엔티티 삭제  (0) 2022.06.01