5. 연관관계 매핑 기초 - (5.2 양방향 연관 관계와 연관관계의 주인1 - 기본)

HotFried·2023년 9월 26일
0

양방향 매핑

양방향으로 매핑을 해도 테이블 연관 관계는 변한 것이 없다.

테이블은 member에서 team을, team에서 member를 외래키 하나로 join 해서 자유롭게 조회할 수 있다.
하지만 객체는 team에 List<Member> members를 추가해야 접근이 가능하다.

Member 엔티티

양방향 관계에서 N(다)에 해당하는 Member엔티티의 team필드는 @ManytoOne 어노테이션을 추가한다.

@Entity
public class Member {

    @Id
    @GeneratedValue
    @Column(name="MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String name;
    private int age;

    @ManyToOne
    @Column(name = "TEAM_ID")
    private Team team;
}

Team 엔티티

양방향 관계에서 1(일)에 해당하는 Team엔티티의 List<Member> members필드는
@OneToMany(mappedBy = "team") 어노테이션을 추가한다.

@Entity
public class Team {

    @Id
    @GeneratedValue
    @Column(name="TEAM_ID")
    private Long id;

    private String name;

    // Member 엔티티에 있는 'team' 필드가 연결되어 있다는 의미
    @OneToMany(mappedBy = "team")
    List<Member> members = new ArrayList<>();
    // 리스트는 초기화 하는 것이 관례다.
	// add 할 때 NullPointException를 방지한다.
}

조회

Team엔티티에서 member엔티티를 조회할 수 있다.

public class JpaMain() {

    public static void main(String[] args) {
        ...

        Team findTeam = em.find(Team.class, team.getId());

        // 이제 team에서도 member를 조회할 수 있다.
        // 역방향 조회 가능
        int memberSize = findTeam.getMembers().size();
    }
}

연관 관계의 주인과 mappedBy

객체는 연관 관계가 2개다.

  • 회원 => 팀, 팀 => 회원 (단방향 연관관계가 두 개 존재하는 것)

테이블은 연관 관계가 1개다.

  • 회원과 팀 사이의 양방향 (member의 FK와 team의 PK를 조인)

  • 객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개다.
  • 객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들어야한다.

  • 테이블은 외래 키(FK) 하나로 두 테이블의 연관관계를 관리한다.
  • MEMBER.TEAM_ID 외래 키 하나로 양방향 연관관계를 가진다.(양쪽으로 Join)

member를 새로운 team에 넣고 싶은데 member에서 team 값을 바꿔야할지 team에서 members 값을 바꿔야할지 딜레마가 온다.

  • member의 team 값을 수정했을 때 외래키 값이 업데이트 되어야 할까,
  • 아니면 team의 members 값을 수정했을 때의 외래키 값이 업데이트 되어야 할까?

DB 입장에서는 member에 있는 FK인 team_id만 업데이트 되면 된다.
결국 member, team 중 하나만 외래키를 관리해야 한다.
연관 관계의 주인을 정해야 하는 것이다.

  • 연관 관계의 주인은 양방향 매핑에서만 나온다.


연관관계의 주인(Owner)

양방향 매핑 규칙

  • 객체의 두 관계중 하나를 연관관계의 주인으로 지정

  • 연관관계의 주인만이 외래 키를 관리(등록, 수정)

  • 주인이 아닌쪽은 읽기만 가능

  • 주인은 amppedBy 속성사용 X

  • 주인이 아니면 amppedBy 속성으로 주인 지정


누구를 주인으로?

  • 외래 키가 있는 곳을 주인으로 정한다.
  • 아래의 그림에서는 Member.team이 연관관계의 주인이 된다.

만약 Member.team이 주인이 된다면
외래키가 Member 엔티티에 존재하기 때문에, Member엔티티에 변경사항이 있을 때 MEMBER 테이블에 업데이트 쿼리가 나갈 것이다.

하지만 Team.members가 주인이 된다면
외래키가 Team 엔티티에 존재하기 때문에, Member엔티티의 변경사항이 있을 때 내가 수정한
TEAM 테이블이 아닌 MEMBER 테이블에 업데이트 쿼리가 나갈 것이다.

-> Team 엔티티를 수정했는데, MEMBER 테이블에 쿼리가 나가기 때문에 혼란스러울 수 있다.


  • DB 입장에서 보면 외래키가 있는 곳이 무조건 N이고 외래키가 없는 곳은 무조건 1이다.
  • 즉, N쪽이 무조건 연관관계의 주인이 된다. = @ManyToOne

참고 :

김영한. 『자바 ORM 표준 JPA 프로그래밍』. 에이콘, 2015.

자바 ORM 표준 JPA 프로그래밍 - 기본편

profile
꾸준하게

0개의 댓글