06. 다양한 연관관계 매핑

연관관계 매핑시 고려사항 3가지#

  • 다중성
    • 다대일, 일대다, 일대일, 다대다
    • 다대다는 실무에서 거의 쓰면 안됨
  • 단방향, 양방향
    • 테이블
      • 외래 키 하나로 양쪽 조인 가능
      • 사실 방향이라는 개념이 없음
    • 객체
      • 참조용 필드가 있는 쪽으로만 참조 가능
      • 한쪽만 참조하면 단방향
      • 양쪽이 서로 참조하면 양방향 (필요할때만 추가적으로 구현)
        • 단방향 두개
  • 연관관계의 주인
    • 객체의 양방향 관계는 참조가 각각 두군데
    • 둘 중 테이블의 외래키를 관리할 곳을 정해야함
    • 외래키가 있는 쪽으로 연관관계 주인을 설정하길 권장

다대일 (N:1)#

  • @ManyToOne

단방향#

public class Member {
...
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
}
public class Team {
...
}

양방향#

public class Member {
...
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
}
public class Team {
...
@OneToMany(mappedBy = "team") // Member의 변수명
private List<Member> members = new ArrayList<>();
...
}

일대다 (1:N)#

OneToMany 샘플 코드

  • @OneToMany
  • 권장하지 않음
    • Team 객체가 MEMBER의 필드를 수정하는 다른 테이블의 데이터를 수정하는 꼴이 발생
    • 업데이트 쿼리 하나 더 나가게됨 (성능상 이슈)

일대다 단방향#

  • 단점
    • 객체와 테이블의 차이때문에 반대편 테이블의 외래키를 관리하는 특이한 구조가 형성됨
    • 다른 테이블에 외래키가 있어서 UPDATE 쿼리가 하나더 나감
  • 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자
  • @JoinColumn 을 꼭 사용해야됨, 아니면 조인 테이블을 새로 생성해서 관리하게 됨

일대다 양방향#

  • 공식적으로 존재하진 않고 @JoinColumn 에 insertable, updatable 옵션을 false로 설정해서 읽기전용으로 만듦
  • 그냥 다대일 양방향 사용하자

일대일 (1:1)#

OneToOne 샘플 코드

  • @OneToOne
  • 주 테이블이나 대상 테이블 중에 외래 키 선택 가능
  • 외래키에 DB 유니크 제약조건 추가
  • 테이블 설계시 유의 사항
    • Member, Locker 둘중에 외래키는 어디에 있는게 좋을까?
      • 하나의 회원에 여러개의 Locker를 가질 수 있다면?
        • Locker에 있는게 유니크 조건만 없애면 가능해짐
        • 대신 양방향으로 구현하게 됨
      • JPA 사용입장에선 Member에 LOCKER_ID 있는게 개발상 편한게 많음

일대일 정리#

  • 주 테이블에 외래키
    • 장점: 주 테이블만 조회에도 대상 테이블에 데이터가 있는지 확인 가능
    • 단점: 값이 없으면 외래키에 null 허용
  • 대상 테이블에 외래키
    • 장점
      • 일대일을 일대다 관계로 변경시 유니크 제약만 없애면 되서 편함
    • 단점
      • 양방향으로 거의 구현됨
      • 프록시 기능의 한계로 지연 로딩이 안되고 즉시 로딩됨 ??
        • 쿼리를 해봐야 null인지 아닌지 확인가능하기 때문 (뒤에 설명)

다대다 (N:M)#

ManyToMany 샘플 코드

  • @ManyToMany
    • @JoinTable
  • 실무에서 쓰면 안됨 -> 편안하게~

왜 쓰면 안되는가#

  • RDB는 다대다를 표현할 수가 없음
  • 관계형 테이블을 추가해서 일대다, 다대일 관계로 풀어내야함
  • 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계 가능

한계 극복#

연결 테이블 샘플 코드

  • 연결 테이블용 객체 추가
  • ManyToMany를
    • 연결 테이블용엔 ManyToOne
    • 대상 테이블엔 OneToMany 로 개선

연결 테이블용 만들시 주의사항#

  • FK 복합키와 따로 Id PK 필드를 뺄지 트레이드오프가 있음
    • PK로 새로 구성하는게 이후 요구사항 추가 변경 시 편했음~

실습 정리#

  • 다대다
    • 권장하지 않음
  • 다대일
    • @ManyToOne 은 mappedBy 옵션이 없어 무조건 연관관계 주인이 되어야 한다
Last updated on