[JPA] 연관관계 매핑(1)
본 포스트는 Inflearn
의 김영한님 강의를 바탕으로 작성했습니다.
객체와 테이블의 패러다임 불일치
먼저 객체와 테이블 사이의 간극을 이해할 필요가 있다. 객체는 참조
를 사용해서 연관된 객체를 찾는다. 그런데 테이블은 외래키 조인
을 통해서 연관된 테이블을 찾는다. 때문에 객체를 테이블에 맞춰서 설계를 하면 객체간의 협력 관계를 만들 수 없다. Member
와 Team
사이의 관계를 통해 이해해보자.
여기서 하나의 Member
는 하나의 Team
에만 속할 수 있다고 가정하자. (1:N)
테이블에 맞춘 객체 설계
Member
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
//Team team 과 같이 참조를 가지는 것이 아니라 식별자를 가진다.
@Column(name = "TEAM_ID")
private Long teamId;
}
Team
@Entity
public clas Team {
@Id @GeneratedValue
private Long id;
private String name;
}
- Team 조회
//member.getTeam()과 같이 바로 조회할 수 없고 id를 구한 후 이를 통해 한번 더 조회해야 한다.
Long TeamId = member.getTeamId();
Team team = em.find(Team.class, TeamId)
위와 같은 경우가 테이블에 맞춰서 객체를 설계한 케이스이다. Member
에서 Team
을 참조로 가지고 있는 것이 아니라 외래키를 그대로 들고 있다.
이렇게 되면 Member에서 Team을 조회할 때, 참조로 바로 Team을 조회할 수 없고 ID를 통해서 다시 조회해야 한다. 이는 객체 지향적인 방법이 아니다.
ORM을 통해서 이러한 패러다임의 불일치를 해결할 수 있다. 객체는 객체대로 모델링하면 가운데서 ORM이 알맞게 매핑해준다.
객체지향 모델링
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
위 코드를 보면 Member
에서 Team
객체를 참조로 가지고 있다. 그런데 Member
테이블에서는 외래키로 TEAM_ID를 가지고 있을 것이다. 이런 차이를 매핑해주는 것이 바로 ORM 이다. 아래 그림을 보자.
JPA는 Member 객체
에 있는 Team 참조를 Member Table
에 TEAM_ID 라는 외래키로 매핑해준다. 이 때 외래키 이름을 지정해줘야 하는데 @JoinColumn
을 통해 지정해줄 수 있다.
양방향 매핑
이제 양방향 매핑에 대해서 탐구해보자. 양방향 매핑일 때는 고려해야 할 점이 좀 있다. 객체
는 양방향 매핑을 하려면 양쪽에 참조를 가져야 한다. 그런데 테이블
은 외래키 하나로 조인을 통해서 양쪽을 이동할 수 있다.
위 그림을 보면 Member 객체
에 있는 Team, Team 객체
에 있는 Member 참조값을 통해서 양쪽을 왔다갔다 할 수 있다.
그런데 테이블은 MEMBER 테이블에 있는 TEAM_ID라는 외래키를 통해서 양쪽을 이동한다.
사실 객체는 양방향을 구현하려면 단방향 두개가 있어야 하는 것이고 테이블은 외래키 하나만 있으면 되는 것이다. 때문에 두 객체 중 한쪽에서 외래키를 관리해야 한다.
연관관계의 주인
객체의 두 관계중 하나를 연관관계의 주인으로 설정하고 주인쪽에서 외래키를 관리해야 한다. 반대쪽(거울)에서는 오직 읽기만 가능하다.
규칙은 간단하다. 외래키를 가지고 있는 곳을 주인으로 설정하면 된다. 1:N관계라면 무조건 N쪽에 외래키가 존재하기 때문에 N쪽을 주인으로 설정하면 된다. 거울쪽에는 mappedBy
설정을 해주면 된다.
- 주의점 : 거울쪽에서 수정을 하더라도 udpate query가 날아가지 않는다. (단순 조회만 가능)
- 객체 관점에서 보면 양쪽 다 변경되는 것이 맞기 때문에 다 변경해주자.
참고 사이트 출처
- https://www.inflearn.com/course/ORM-JPA-Basic/dashboard