JPA 5장 연관관계 매핑 기초

wisdom·2022년 8월 27일
0

백엔드 개발자라면?

목록 보기
36/42

김영한님의 자바 ORM 표준 JPA 프로그래밍 책으로 공부하면서 정리했습니다.

객체 관계 매핑

@ManyToOne

  • 다대일 관계라는 매핑 정보

@JoinColumn(name="team_id")

  • 조인 칼럼은 외래키를 매핑할 때 사용한다.
  • name 속성에는 매핑할 외래 키 이름을 지정한다.
  • 회원과 팀 테이블이 있을 때 team_id 외래키로 연관관계를 맺기 때문에 이 값을 지정하면 된다.
  • 생략 가능
    - 생락하면 외래키를 찾을 때 기본 전략을 사용한다.
    - 필드명_참조하는테이블의칼럼명
    - team_TEAM_ID

JPA 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태여야 한다.

연관관계가 있는 엔티티를 조회하는 방법

  • 객체 그래프 탐색
    - 객체 연관관계를 사용한 조회
  • 객체지향 쿼리 사용
    - JPQL

양방향 연관관계

  • 일대다 관계는 여러 건과 연관관계를 맺을 수 있으므로 컬렉션을 사용해야 한다.
  • 데이터베이스 테이블은 외래 키 하나로 양방향 조회를 할 수 있다. 따라서 단방향 관계에서 양방향 관계로 변경하더라도 데이터베이스에 추가할 내용은 전혀 없다.

연관관계의 주인

mappedBy

  • 양방향 매핑일 때 사용
  • 반대 쪽 매핑의 필드 이름을 값으로 주면 된다.

그런데 mappedBy는 왜 필요할까?

  • 엔티티를 양방향 연관관계로 설정하면 객체의 참조는 둘인데 외래키는 하나다. 따라서 둘 사이에 차이가 발생한다. 그렇다면 둘 중 어떤 관계를 사용해서 외래키를 관리해야 할까?
    - 그 차이 때문에 mappedBy가 필요하고, JPA에서는 두 객체 연관관계 중 하나를 정해서 테이블의 외래키를 관리해야 하는데 이것을 연관관계 주인이라 한다.
    - 어떤 연관관계를 주인으로 정할지 mappedBy 속성을 사용하면 된다.

양방향 매핑의 규칙: 연관관계의 주인

  • 양방향 연관관계 매핑 시 지켜야 할 규칙이 있는데 두 연관관계 중 하나를 연관관계의 주인으로 정해야 한다.
  • 연관관계의 주인만이 데이터베이스 연관관계와 매핑되고 외래키를 관리(등록,수정,삭제)할 수 있다.
  • 반면에 주인이 아닌 쪽은 읽기만 할 수 있다.
  • 주인은 mappedBy 속성을 사용하지 않는다.
  • 주인이 아니면 mappedBy 속성을 사용해서 속성의 값으로 연관관계의 주인을 지정해야 한다.

연관관계 주인은 어떻게 정할까?

  • 연관관계 주인 -> 외래키 관리자를 선택하는 것
  • 연관관계의 주인은 외래키가 있는 곳으로 정해야 한다.
  • 데이터베이스 테이블의 다대일, 일대다 관계에서는 항상 다 쪽이 외래키를 가진다.
  • @ManyToOne 은 항상 연관관계의 주인이 되므로 mappedBy를 설정할 수 없다.
  • 따라서 @ManyToOne에는 mappedBy 속성이 없다.

순수한 객체까지 고려한 양방향 연관관계

  • 연관관계의 주인에만 값을 저장하고 주인이 아닌 곳에는 값을 저장하지 않아도 될까?
    - 객체 관점에서 양쪽 방향에 모두 값을 입력해주는 것이 가장 안전하다.
    - 양쪽 방향 모두 값을 입력하지 않으면 JPA를 사용하지 않는 순수한 객체 상태에서 심각한 문제가 발생할 수 있다.
  • 객체의 양방향 연관관계는 양쪽 모두 관계를 맺어주자.

연관관계 편의 메서드

  • 양방향 연관관계는 결국 양쪽 다 신경써야 한다.
  • 아래 코드처럼 멤버와 팀 각각 호출하다보면 실수로 둘 중 하나만 호출해서 양방향이 깨질 수 있다.
member.setTeam(team);
team.getMembers().add(member);
  • 양방향 관계에서 두 코드는 하나인 것처럼 사용하는 것이 안전하다.
  • 아래의 코드처럼 메서드 하나로 양방향 관계를 모두 설정하도록 할 수 있다.
    - 주의사항: 연관관계를 변경하는 경우가 있기 때문에 기존 관계를 제거하는 코드가 필요하다.
public class Member {
	private Team team;
	
	public void setTeam(Team team) {

		if(this.team != null) {
			this.team.getMembers().remove(this);
		}

		this.team = team;
		team.getMembers().add(this);
	}
}

양방향의 장점

  • 단방향과 비교해서 반대방향으로의 객체 그래프 탐색 기능이 추가된 것 뿐

연관관계의 주인을 정하는 기준

  • 단방향은 항상 외래키가 있는 곳을 기준으로 매핑하면 된다.
  • 양방향의 경우, 비즈니스 중요도를 배제하고 단순히 외래키 관리자 정도의 의미를 부여하고 주인을 정해야 한다.

연관관계의 주인은 외래키의 위치로 접근해야함

profile
문제를 정의하고, 문제를 해결하는

0개의 댓글