[3] JPA 프로그래밍 (7) - 연관관계 매핑 2 / @ManyToOne @OneToOne 등

김정욱·2021년 3월 5일
0

[3] JPA 프로그래밍

목록 보기
7/15
post-thumbnail

연관관계 매핑시 고려사항

  • 다중성
    • 다대일 [N:1]
    • 일대다 [1:N]
    • 일대일 [1:1]
    • 다대다 [N:M]
  • 단방향, 양방향
  • 연관관계 주인

다대일 [N:1]

[ 설명 ]

  • 다대일 의 뜻 : N:1관계에서 연관관계 주인이 N인 경우
  • 가장 많이 사용되는 연관관계
  • DB에서는 반드시 1:N 관계에서 N에 해당하는 테이블에 외래키(FK)가 들어간다
    --> 1에 FK가 들어가면 말이 안됨
    (TeamMemberId가 있다면 배열이 DB에 들어가지 않는 한 하나의 TEAM_ID에 여러개의 Member가 들어갈 수 없음)

[ 단방향 ]

  • 과정 [N 객체]
    • FK1의 객체를 삽입
    • @ManyToOne + @JoinColumn(name = "{1의 PK이름}")
      ex)

[ 양방향 ]

  • 과정 [N 객체]
    • 단방향 설정 + 연관관계 메서드
  • 과정 [1 객체]
    • List<객체> 변수 선언
    • @OneToMany(mappedBy = {N의 필드이름})
      ex)

일대다 [1:N]

[ 설명 ]

  • 일대다 의 뜻 : 1:N관계에서 연관관계 주인이 1인 경우
  • 1:N관계에서 항상 NFK를 넣어주기 때문에 잘 쓰이지 않는 관계
  • 기능적으로도 관리하는 외래 키가 다른테이블에 있어서 추가적인 UPDATE 쿼리가 나간다 --> 비효율적
  • 만약 꼭 필요하다면 다대일 양방향 매핑 권장
  • 사용시 @JoinColumn을 꼭 사용해야함
    (default가 JoinTable이라서 테이블이 생성되기 때문)

[ 단방향 ]

  • 과정 [1 객체]
    • FKList<>의 객체를 삽입
    • @OneToMany + @JoinColumn(name = "{1의 PK이름}")
      ex)

[ 양방향 ]

  • 과정 [1 객체]
    • 단방향 설정 + 연관관계 메서드
  • 과정 [N 객체]
    • 1의 객체를 변수로 선언
    • @ManyToOne
    • @JoinColumn(name = "1의 PK", insertable = false, updateable = false)
      : 조회만 하도록 강제로 만들어 주는 것!
      ex)
  • 즉 , 다대일 연관관계에서 양방향 연관관계와 설정은 같으나 mappedBy가 빠지고, insertable, updateablefalse 처리해서 강제로 조회만 하게만들어 준것 !
    --> 굳이 사용할 일이 없음
    --> 다대일 양방향을 사용하자

일대일 [1:1]

[ 설명 ]

  • 양쪽 테이블 모두 FK를 가질 수 있음
    • 주 테이블FK 삽입
    • 대상 테이블FK 삽입
      (주 테이블 ? --> 더 자주 사용되는 테이블)
  • 어떤 테이블에 FK를 삽입하고 연관관계 주인이 될지는 고려해볼 문제
    --> 그러나 보통 주 테이블FK를 넣고 연관관계 주인 설정을 한다
  • FKDB 유니크 제약조건 추가해야함
    -->
    1:1이기 때문
    (사실 데이터가 그렇게 안오면 괜찮지만, 혹시모르니 해놔야함)

[ 단방향 ] - 주 테이블

  • 다대일 관계 설정과 매우 유사 (어노테이션만 다름)
  • 주 테이블 객체
    • 대상 테이블 객체를 참조하는 변수 선언
    • @OneToOne + @JoinColumn(name = "대상테이블 PK")
      ex)

[ 양방향 ] - 주 테이블

  • 주 테이블 객체
    • 단방향 설정 + 연관관계 메서드
  • 대상 테이블 객체
    • 주 테이블 객체 참조하는 변수 선언
    • @OneToOne(mappedBy = "연관관계 주인의 필드명")
      ex)

[ 단뱡향 ] - 대상 테이블 (불가능)

  • 대상테이블FK를 저장하는 단방향 관계는 불가능
  • JPA에서 지원하지 않음 / 강제로 할수도 없음

[ 양방향 ] - 대상 테이블 (가능)

  • FK대상 테이블에서 관리하고 주 테이블의 변수는 읽기전용으로 사용된다.
  • 매핑하는 방법은 일대일 주 테이블 양방향 과 같다

[ 1:1 정리 ]

  • 1:1 연관관계시 주 테이블FK를 넣는 것이 단순하고 많이 사용
  • DBA와 협의 후 필요에 따라 대상 테이블FK를 넣는 양방향은 고려해볼 만 하다
  • 주 테이블에 외래 키
    • 장점
      : 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
    • 단점
      : 값이 없으면 외래 키에 null값 허용 해야함
  • 대상 테이블에 외래 키
    • 장점
      : 주 테이블과 대상 테이블을 일대다로 변경시 테이블 구조 유지
      (나중에 Member가 여러개의 Locker를 쓰게되면 어차피 Locker연관관계 주인이 되어야 하기 때문에 유지)
    • 단점
      : 프록시 기능의 한계로 지연 로딩 설정해도 항상 즉시 로딩
      (값이 없으면 Null을 넣어줘야 해서 어차피 확인해야 하기 때문에 즉시 로딩됨)

다대다 [N:M]

[ 설명 ]

  • RDB에서 N:M 관계는 테이블 2개로 표현이 불가능하다
    --> 테이블을 추가해서 1:N M:1 로 풀어내야함
  • 객체에서는 N:M 이 가능해서 JPA가 @ManyToMany을 통해 지원함
  • 서로의 PK를 지정해서 알아서 테이블로 만들어주는 기능인데 권장 X
    (딱 지정한 Column만 넣을 수 있기 때문
    --> 차라리 @Entity를 직접만들어서 원하는 Column추가하는것 권장O)
  • 즉, 실무에서 @MayToMany 사용 X

[ 사용 ]

  • 기본적으로 양방향으로 설계
  • 한쪽
    • List<참조객체> 선언
    • @ManyToMany
    • @JoinTable(name="", joinColumns =@JoinColumn(name="한쪽 PK명"), inverseJoinColumns = @JoinColumn(name = "다른쪽 PK명")
      ex)
  • 다른쪽
    • List<참조객체> 선언
    • @ManyToMany(mappedBy = "연관관계 주인 필드명")
      ex)

[ 한계 ]

  • @ManyToMany를 사용한 다대다 연결은 내가 지정한 Column만 가능하다
  • 사용하기에 편해보이지만 유연성이 없어서 실무에서 사용하지 X

[ 대안 ]

  • 실무에서는 실제로 두 테이블을 사이에 새로운 @Entity선언해서 사용
  • N:M --> 1:N M:1로 풀어서 사용한다!!
  • 내가원하는 Column추가할 수 있는 유연성이 생김!

[ 정리 ]

  • N:1 (다대일) 관계 & 1:N(주 테이블 FK)로 대부분 관계 정의 가능
  • N:M은 반드시 1:N & M:1로 분리해서 @Entity 추가 생성해 사용
  • 연관관계를 구현하기 위해 적절한 어노테이션옵션 지정을 기억하자
profile
Developer & PhotoGrapher

0개의 댓글