과정을 즐기자

연관관계 매핑 본문

Spring Data

연관관계 매핑

320Hwany 2022. 11. 29. 21:45

연관관계 매핑

테이블은 외래 키로 조인을 사용해서 연관된 테이블을 찾는다. 객체는 참조를 사용해서 연관된 객체를 찾는다.
테이블과 객체의 이런 차이를 없애기 위해 연관관계 매핑을 사용한다.

예를들어 Member와 Team이 있다고 하자. 한 team에는 여러 명의 member가 있을 수 있다.
먼저 테이블을 만들어보면 member와 team은 N:1 관계이고 member 쪽이 외래 키로 team_id를 가진다.
테이블에서는 외래 키 하나로 member에서도 team을 찾을 수 있고 team에서도 member를 찾을 수 있다.

단방향 매핑

이제 객체를 보자. Member가 참조를 사용하기 위해 teamId 대신 team을 가져야 한다.
@JoinColumn은 외래 키를 매핑할 때 사용한다. 매핑할 외래 키 이름을 속성 name으로 적어주면 된다.

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

또한 연관관계를 설정해주어야 한다. (set 메소드를 사용하는건 좋지 않지만 간단한 예시를 위해 사용함)

public void setTeam(Team team) {
    this.team = team;
}

단방향 매핑만으로 테이블과 객체의 연관관계 매핑은 완성되었다. 이러한 방식으로 가능하면 단방향 매핑만으로 끝내는 것이 좋다.
하지만 비즈니스에 따라 반대편에서도 조회하는 기능이 필요할 수도 있다. 이러한 경우에는 양방향 매핑이 필요하다.

양방향 매핑

양방향 매핑에서는 연관관계의 주인을 정해야 한다. 연관관계의 주인만이 데이터베이스 연관관계와 매핑되고 외래 키를 관리한다.
주인이 아닌 쪽은 읽기만 할 수 있다. 연관관계의 주인을 정하는 것은 외래 키 관리자를 선택하는 것이다. 따라서 연관관계의 주인은
외래 키의 위치와 관련해서 N:1에서 N쪽으로 정해야한다. 비즈니스의 중요도로 접근하면 안된다.

양방향 매핑은 단방향 매핑으로 이미 완성된 연관관계 매핑에서 반대편에서도 조회할 수 있도록 해주면 된다.
반대편에 mappedBy 부분을 추가하자. 이때 NPE를 막기 위해 new ArrayList<>()를 적어주는 것이 관례이다.

@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>(); 

또한 연관관계를 설정해주는데 객체 관점에서는 양쪽 방향에 모두 값을 입력해주는 것이 안전하다.
JPA를 사용하지 않는 순수한 객체 상태에서는 문제가 될 수 있기 때문이다.
예를 들면 JPA를 사용하지 않는 테스트 코드를 작성할 때가 있을 수 있다.

또한 이때 양쪽 모두에 메소드를 작성하는 방법보다 한쪽의 메소드 하나로 모두 처리하는 방법이 좋다.
이렇게 한 번에 양방향 관계를 설정하는 메소드를 연관관계 편의 메소드라고 한다.

public void setTeam(Team team) {
    this.team = team;
    team.getMembers().add(this);
}

이러한 양방향의 장점은 반대방향으로 객체 그래프 탐색 기능이 추가된 것뿐이다. 하지만 양방향 매핑은 복잡하다.
따라서 꼭 필요한 경우가 아니라면 단방향 매핑을 사용하도록 하자.

출처 : 자바 ORM 표준 JPA 프로그래밍(김영한)

'Spring Data' 카테고리의 다른 글

고급 매핑  (0) 2022.12.04
다양한 연관관계 매핑  (0) 2022.12.02
엔티티 매핑  (0) 2022.11.29
영속성 관리  (0) 2022.11.27
JPA를 사용하는 이유  (0) 2022.11.27