JPA 연관관계 설정, 옵션

이준우·2024년 2월 16일
0
post-thumbnail
  • 연관관계 매핑시 고려 사항 3가지
    • 다중성
      • 다대일 : @ManyToOne
      • 일대다 : @OneToMany
      • 다대일 : @OneToOne
      • 다대일 : @ManyToMany
        • 실무에서는 사용 ❌
      • 데이터베이스 관점에서의 다중성이 헷갈릴 경우 반대로 생각 ➡️ 대칭성이 있기 때문
        • ex) 일대다의 반대는 다대일
    • 단방향, 양방향
      • 테이블(DB 관점)
        • 외래 키 하나로 양쪽 조인 가능 ➡️ 방향이라는 개념 ❌
      • 객체
        • 참조용 필드가 있는 쪽으로만 참조 가능
        • 한쪽만 참조하면 단방향, 양쪽이 서로 참조하면 양방향(단방향이 2개, 양방향이라는 개념 ❌)
    • 연관관계의 주인
      • 객체 양방향 관계는 A→B, B→A 처럼 참조가 2군데 ➡️ 외래키를 관리할 곳을 지정
      • 연관관계의 주인은 외래 키를 관리하는 참조를 뜻함
      • 주인의 반대편 : 외래키에 영향 ❌, 단순 조회만 가능
      • 다대일의 연관관계의 주인은 앞에 부분인 ‘다’, 일대다의 연관관계의 주인은 앞에 부분인 ‘일’이다.
        ➡️ 앞에 부분을 연관관계의 주인으로 볼 수 있다.

다대일 [N : 1]

  • 단방향

    • 외래키는 ‘다’쪽에 존재해야 함.

    • 외래키가 있는 곳에 참조를 걸고 연관관계 매핑을 하면 된다.

    • Team은 Member를 참조하고자하는 의지 ❌

  • 다대일 양방향

    • Team에 Member List를 추가
    • mappedBy를 통해 연관관계의 주인이 아님을 명시
      • mappedBy가 지정된 엔티티는 FK를 조회만 가능

일대다

  • 단방향

    • 권장하지 않는 모델, 실무에서는 거의 가져가지 않는다.

    • Member 쿼리 → Team 쿼리 → Member UPDATE 쿼리

    • 1 부분에서 FK를 관리하지만 DB 설계상 N쪽에 FK가 들어갈 수 밖에 없음

    • 객체와 테이블의 차이 때문에 반대편 테이블의 외래 키를 관리하는 구조 ➡️ ORM이 억지로 해결

    • @JoinColumn을 꼭 사용.

      • 테이블의 왜래 키와 매핑할 때 사용하는 어노테이션
      • 속성
        • name : 단순히 칼럼명을 만들어 주는 것
        • referencedColumnName : 어떤 칼럼을 참조하는지를 지정
      • 사용하지 않을 경우 JPA가 중간에 테이블을 하나 추가하는 조인 테이블 방식을 사용
        ➡️ 성능, 운영상 단점
    • 단점
      - 엔티티가 관리하는 외래키가 다른 테이블에 존재 ➡️ 어마어마한 단점
      - 연관관계를 관리를 위해 추가로 UPDATE SQL 실행

      ➡️ 다대일 양방향으로 해서 비슷하게 사용(연관관계 주인을 member로 지정), 객체적으로는 손해지만 DB에 설계관점을 맞추어 유지보수에 장점을 가짐

  • 양방향

    Member에 추가

    • 공식적으로 존재 ❌
    • @JoinColumn(insertable=false, updatable=false)
      • insertable : 엔티티가 저장될 때 FK의 값을 삽입할지 여부를 지정
      • updatable : 엔티티가 없데이트될 때 FK의 값을 업데이트할지 져부를 지정
      • Member와 Team 모두 연관관계의 주인이기 때문에 Member의 연관관계 주인을 무효화 ➡️ 읽기 전용

일대일 관계 [1:1]

  • 일대일 관계는 그 반대도 일대일

  • 주 테이블이나 대상 테이블 중에 외래 키 선택 가능 ➡️ 둘 중 한 곳만

  • 외래 키에 데이터베이스 유니크 제약조건이 추가가 되어야함

  • 단방향

    • 유니크 조건은 MEMBER 테이블, LOCKER 테이블 둘 중 아무 곳에 존재해도 상관 ❌

  • 양방향

    Locker에 Member 추가

  • 일대일 : 대상 테이블에 외래 키 단방향

    • Member가 주인이 되고 싶은데 FK가 반대에 있는 경우 ➡️ 일대다 단방향 같은 경우
    • 지원 ❌, 방법 ❌
  • 일대일 : 대상 테이블에 외래 키 양방향

    • 외래키를 반대 테이블로 옮김
  • 주 테이블에 외래 키

    • 객체지향 개발자 선호
    • JPA 매핑 편리
    • 장점 : 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능 ➡️ 조회의 이점
    • 단점 : 값이 없으면 외래 키에 null 허용 ➡️ DB관점에서 치명적
  • 대상 테이블에 외래 키(양방향으로 개발)

    • 전통적인 데이터베이스 개발자 선호
    • 장점 : 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지 ➡️ 유니크 제약만 제거
    • 단점 : 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩

다대다 [N:M]

  • 관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계 표현 ❌ ➡️ 연결 테이블을 추가해 일대다, 다대일 관계로 풀어내야함

  • 객체는 컬랙션을 사용해서 객체 2개로 다대다 관계 가능

  • @ManyToMany 사용

  • @JoinTable로 연결 테이블 지정

    • Member_Product와 같은 별도의 테이블을 만들어줌
  • 단방향, 양방향 가능

  • 실무에서 사용 ❌

  • 단방향

    Member에 추가

  • 양방향

    product에 추가

  • 한계

    • @JoinTable에 의해 생긴 연결 테이블은 연결의 역할만 하기 때문에 추가적인 필드를 가질 수 없다.
    • 의도하지 않은 쿼리가 나갈 수 있음
  • 한계 극복

    • 연결 테이블용 엔티티 추가

    • @ManyToMany ➡️ @OneToMany, @ManyToOne

      Member측 ManyToMany를 OneToMany로 변경

      Product측 ManyToMany를 OneToMany로 변경

      테이블 연결용 엔티티

profile
잘 살고 싶은 사람

0개의 댓글