05. 연관관계 매핑 기초

목표#

  • 객체와 테이블 연관관계 차이를 이해
  • 객체 참조와 테이블 외래키를 매핑
  • 용어 이해
    • 방향(Direction): 단방향: 양방향
    • 다중성(Multiplicity): N:1, 1:N, 1:1, N:M
    • 연관관계의 주인(Owner): 객체 양방향 연관계는 관리 필요
      • JPA계의 포인터 (Hell yeah!)

단방향 연관관계#

객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다. - 조영호 (객체지향의 사실과 오해)

예제 시나리오#

  • 회원과 팀
  • 회원은 하나의 팀에만 소속될 수 있음
  • 회원과 팀은 다대일 관계
    • 회원:팀 = N:1

객체를 테이블에 맞추어 모델링#

  • 테이블은 외래키로 조인
    • 첫 예시에선 Entity zmffotmdp
  • 객체는 참조를 사용해서 연관된 객체를 찾음

단방향 연관관계로 개선#

예제 코드

양방향 연관관계와 연관관계의 주인#

예제 코드

양방향 연관관계#

  • 양방향 매핑
    • 테이블에 연관관계는 한쪽의 FK로 양방향 관계가 표현 가능
@Entity
public class Member {
...
private Team team; // MEMBER 테이블에 TEAM_ID FK 필드가 있음
...
}
@Entity
public class Team {
...
@OneToMany(mappedBy = "team") // 변수명 기입
private List<Member> members = new ArrayList<>(); // TEAM 테이블엔 FK 정보가 없음
...
}
  • 양방향이 좋은가?
    • 왠만하면 단방향이 덜복잡하고 좋음

연관관계의 주인 😭#

  • 연관관계의 주인과 mappedBy
    • mappedBy = JPA의 멘탈붕괴 난이도
    • 처음에 이해하기 어려움
    • 객체와 테이블간에 연관관계를 맺는 차이를 이해하면 도움

객체와 테이블이 관계를 맺는 차이#

  • 객체 연관관계 키포인트 2개
    • 회원 -> 팀 (team 멤버 변수) (단방향)
    • 팀 -> 회원 (members 멤버 변수) (단방향)
  • 테이블 연관관계 키포인트
    • MEMBER.TEAM_ID (FK) (양방향)
  • 객체의 단방향 관계 둘중 하나로 관리를 해야함
    • Member.team 을 바꿀지 Team.members 를 바꿀지 고민이 됨
    • DB 입장은 MEMBER.TEAM_ID FK 하나만 관리하면 됨

연관관계의 주인 (Owner)#

  • 양방향 매핑 규칙
    • 연관관계의 주인만이 외래 키를 관리 할 수 있음 (등록, 수정)
    • 주인이 아닌쪽은 읽기만 가능
    • 주인은 mappedBy 속성 사용 X
  • 누구를 주인으로 하는가?
    • 외래 키가 있는 곳을 주인으로 정하자 (Member.team 이 주인)
      • 반대로하면 이해가 힘듦 (Team 객체를 수정했는데 MEMBER 테이블이 변하는 헷갈리는 상황이 발생)
      • 성능 이슈도 있음
    • 가짜 매핑 - 주인의 반대편 (Team.members)

양방향 매핑에서 가장 많이 하는 실수#

  • 매핑시 연관관계의 주인에 값을 입력해야 한다.
  • 순수 객체 상태를 고려해서 항상 양쪽에 값을 설정하자
  • 연관관계 편의 메소드를 생성하자
    • 실습 코드
    • 가급적 한쪽에서만 구현하자 (둘다 있으면 고려사항이 많아짐)
  • 양방향 매핑시 무한 루프를 조심하자
    • toString(), lombok, JSON 생성 라이브러리
    • Entity 클래스는 Response로 직접 쓰지 말자
      • DAO를 DTO로 변환해서 반환하자

양방향 매핑 정리#

  • 단방향 매핑만으로도 이미 연관관계 매핑은 완료
  • 양방향 매핑은 반대 방향 조회 (객체 그래프 탐색) 기능 추가일 뿐
  • JPQL에서 역방향으로 탐색할 일이 많음
  • 양방향은 필요할때만 추가하자
  • 연관관계의 주인은 외래키의 위치를 기준으로 정해야한다

느낀점#

  • 단방향으로 설정 (객체 입장에서 양방향으로 있으면 복잡도가 너무 올라감)
    • 이후 필요하게 되었을 때, 어쩔 수 없이 양방향으로 만듦
    • 이때 연관관계 주인 설정을 정확히
  • 연관관계의 주인 -> 외래키를 가지는 엔티티가 주인
    • 다른 객체는 mappedBy 로 주인이 아니라는 설정을 해줘야 함
Last updated on