연관관계의 주인

public class Member {
    @ManyToOne
    @JoinColumn(name = "team_id")
    private Team team;
...
}

이렇게만 있어도 member.getTeam() 으로 객체그래프를 탐색할 수 있다.
하지만 반대쪽인 Team 객체에서는 List<Member> members 등과 같은 필드가 없기 때문에 Team에서 Member객체를 탐색할 수 없다. 추천하지는 않지만 아래와 같이 Team에서도 Member를 탐색할 수 있게끔 양방향관계를 갖고있다고 생각해보자.

public class Team {
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();
...
}

엄밀히 말해서 엔티티에서는 양방향 관계란 있을 수 없다.
위와 같은 코드는 단방향관계가 두개인 것이다.

  1. member.getTeam();
  2. team.getMembers();

반면 DB에서는 테이블 외래키 하나만으로 양방향 연관관계를 맺을 수 있다.

이처럼 엔티티는 단방향 연관관계 두개, 테이블은 양방향 연관관계 하나로 패러다임의 불일치가 발생하게 된다.

이러한 차이로, JPA에서는 두 객체 연관관계중 하나를 정해서 테이블의 외래키를 관리하게 되는데 이것을 연관관계 주인이라 한다.

규칙

  • 연관관계의 주인만이 DB연관관계와 매핑되고, 외래키를 관리(등록,수정,삭제) 할 수 있다.
  • 반면 주인이 아닌 쪽은 읽기만 가능하다.
  • 주인은 mappedBy 속성을 사용하지 않는다
  • 주인이 아니라면 mappedBy속성을 사용해서 속성의 값으로 연관관계 주인을 지정한다.
  • 위와 같은 코드에선 연관관계가 두개 나타난다.
    • 회원 -> 팀 (Member.team)
    • 팀 -> 회원 (Team.members)
    • 연관관계의 주인은 외래키가 있는 곳이다.
    • 회원테이블이 외래키를 가지고있으므로 Member.team이 주인이된다.
    • 반대로 주인이 아닌 Team.members에서는 mappedBy="team" 옵션을 사용해서 주인이 아님을 설정한다.
    • mappedBy의 값인 "team" 은 연관관계의 주인인 Member엔티티의 team 필드를 말한다.

결론

  • DB는 일대다 관계에서 '다' 쪽에 외래키가 위치한다.
  • 따라서 연관관계의 주인은 '다' 쪽이다
  • 곧 '다' 쪽이 연관관계의 주인이다.
  • 그러므로 '일'쪽에서 mappedBy로 연관관계의 주인이 아님을 명시하고, 그 값으로는 연관관계 주인인 엔티티의 필드를 명시해준다.

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

@EntityGraph  (0) 2020.02.11
순수 JPA레포지토리의 페이징과 스프링 데이터 JPA레포지토리의 페이징.  (0) 2020.02.10
준영속 상태  (0) 2020.01.16
플러시  (0) 2020.01.16
영속성 컨텍스트  (0) 2020.01.16

+ Recent posts