[JPA] 4.다양한 연관관계 매핑

Updated:

다양한 연관관계 매핑

이 게시글을 통해 객체와 테이블간의 연관관계 차이를 이해하고 객체의 참조와 테이블의 외래키를 매핑하는 것을 목표로 한다

배경지식

앞선 JPA 3번 게시글에서 배운 내용을 간략하게 리마인드해보자

다중성

  • @ManyToOne: 다대일
  • @OneToMany: 일대다
  • @OneToOne: 일대일
  • @ManyToMany: 다대다

실무에서 다대다 관계는 사용하지 않는 것이 좋다. 그 이유와 대체방안에 대해 아래에서 알아보자

단방향과 양방향

  • 단방향은 한쪽의 객체에만 반대쪽 객체로의 참조값 필드가 존재한다
  • 양방향은 양쪽의 객체 모두 반대쪽 객체로의 참조값 필드가 존재한다
    • 정확히 말하자면 양방향은 서로를 향한 단방향이 2개 있는 것과 같다

양방향 연관관계에서 테이블과 객체의 차이점

양방향 연관관계에서 테이블은 외래키 하나만으로 두 테이블이 연관관계를 맺을 수 있지만, 객체는 양쪽 객체의 참조값 필드 즉, 참조가 2군데 존재한다

  • 테이블은 외래키를 이용한 조인으로 양쪽 테이블에서 반대 테이블 접근이 가능하다
  • 객체는 양쪽 객체에 반대쪽 객체의 참조값 필드가 있는 경우에만 접근이 가능하다

연관관계의 주인

  • 위에서 언급한 테이블과 객체의 차이점으로 인해, 객체 측 2군데의 참조 중 테이블 측 1개의 외래키를 관리할 곳을 지정해야한다
  • 연관관계의 주인이 아닌 참조는 외래키에 영향을 주지 않고 조회만 가능하다

1. 다대일 관계

1-1. 다대일 단방향

가장 많이 사용하는 연관관계이며 간단하다

jpa1

  • 테이블에서 외래키는 항상 다쪽에 위치한다
  • 객체에서 단방향 연관관계 역시 한쪽에만 참조가 존재한다
  • 단순히 하나의 외래키와 참조를 매핑하면 된다

1-2. 다대일 양방향

jpa2

  • 테이블에서 외래키는 마찬가지로 항상 다쪽에 위치한다
  • 객체에서 양방향 연관관계는 양쪽 객체에 모두 참조가 생겨 총 2개의 참조가 존재한다
    • 필요에 따라 단방향에서 양방향으로 바꾸는 경우에는 참조가 필요한 객체 측에서 참조값 필드만 추가해주면 된다
      • 어차피 해당 참조값 필드로는 조회만 가능하고 테이블에는 영향을 미치지 않는다
      • 코드에서는 @OneToMany를 추가하고 mappedBy 속성을 넣어주면 된다
  • 테이블의 외래키를 다대일 중 다 측의 객체에서 관리한다

2. 일대다 관계

실무에서 거의 사용하는 경우가 드물다

2-1. 일대다 단방향

jpa3

  • 특이하게 테이블 측에서 다쪽에 위치한 외래키를 연관관계의 주인인 객체 측 일쪽에 위치한 참조로 매핑하는 방식이다
  • DB에 조회 이외의 작업은 일대다 관계 중 다 측에서밖에 수행할 수 없다
  • 아래 코드를 보면 더 쉽게 이해가 갈 것이다
//기존 로직
member.setTeam(team);

//일대다 단방향에서의 로직
team.members.add(member);
  • 이렇게 헷갈리게 설계하는 것보다 차라리 다 측의 객체에도 참조를 추가하여 양방향으로 만들고 해당 참조에서 외래키를 관리하도록 하는 것이 좋다
    • 즉, 일대다 단방향을 사용해야 한다면 차라리 다대일 양방향을 사용하자

2-2. 일다다 양방향

jpa4

  • 공식적으로 존재하지 않는 매핑이다
  • 대신 다대일 양방향을 사용하자

3. 일대일 관계

일대일 중 어느쪽 테이블에 외래키를 넣을지 선택할 수 있다. 단, 외래키에 DB unique 제약조건을 추가해줘야 한다

3-1. 일대일 단방향

일대일 단방향 연관관계에서 외래키가 있는 테이블의 반대편 객체에서 연관관계의 주인으로써 동작하는 것은 JPA가 지원하지 않는다

jpa5

  • 왜래키가 있는 곳이 연관관계의 주인이다
  • 다대일 관계와 마찬가지로 연관관계의 주인 측에는 @JoinColumn을 적고, 반대 측에는 mappedBy 속성을 명시한다

3-2. 일대일 양방향

외래키가 있는 테이블의 반대편 객체에서 연관관계의 주인으로써 동작하는 것은 일대일 단방향 관계에서 불가하기 때문에 이는 일대일 양방향 연관관계를 이용하여 해결한다

jpa6

  • 다대일 양방향 연관관계와 마찬가지로 양방향 연관관계를 이용하여 외래키와 참조값이 서로 반대에 위치하는 문제를 해결한다

3-3. 일대일 연관관계의 딜레마

일대일 연관관계는 어느쪽 테이블이든 외래키를 넣을 수 있기 때문에 DB 설계시에 양측의 장단점을 살펴보고 선택해야한다

  • 주 테이블에 외래키를 놓는 경우
    • 주 테이블만 조회해도 대상 테이블의 데이터 유무가 확인 가능하고 JPA 매핑이 편리하다는 장점을 가진다
    • 대상 테이블 데이터가 없다면 외래키에 null값을 허용한다는 단점이 존재한다
  • 대상 테이블에 외래키를 놓는 경우
    • 일대일 양방향 연관관계를 이용하여 해결한다
    • 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변강할때 테이블 구조가 유지된다는 장점을 가진다
    • JPA 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩된다는 단점이 있다

4. 다대다 관계

@ManyToMany는 실무에서 사용하지 않는다

객체는 다대다 관계를 지원하지만 테이블에서는 다대다관계가 따로 존재하지 않고 일대다, 다대일 관계를 통해 풀어내야 한다는 차이점이 존재한다

  • JPA에서 @ManyToMany를 통해 중간 테이블을 자동으로 만들어주기는 하지만, 해당 테이블은 양쪽 테이블의 PK값만을 외래키로 들고 나머지 필드값들을 추가할 수 없다는 명확한 단점이 존재하기 떄문에 실무에서 사용하지 않는다
  • 이를 해결하기 위해 중간 테이블을 개발자가 직접 엔티티로 만들어 일대다 다대일 관계로 풀어낸다

Tags: ,

Categories:

Updated:

Leave a comment