프로그래밍/JPA

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

후르트링 2022. 4. 14. 16:17
728x90

객체에서 연관 관계를 설정하고 주인을 정하여 외래키를 다루는 법을

이전 글에서 다루었습니다.

이번에는 연관관계 매핑을 하는 다양한 방법에 대해 알아보겠습니다.

엔티티 연관 관계 매핑 시 고려해야 할 것

다중성

다중성은 다음과 같이 4가지의 종류가 있습니다

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

단방향, 양방향

  • 테이블은 외래키 하나로 조인을 사용하여 양방향으로 쿼리가 가능하므로 방향의 개념이 없습니다.
  • 객체의 경우에는 참조용 필드가 있는 경우에만 연관된 객체를 조회할 수 있습니다.
    • 객체가 한쪽만 참조한다면 단방향, 객체가 양쪽이 서로 참조한다면 양방향이라고 할 수 있습니다.

연관관계의 주인

연관 관계의 주인 : 외래 키를 관리하는 참조

데이터베이스는 외래 키 한개로 두 테이블이 연관관계를 가집니다.

그러나 객체의 양방향 관계는 양쪽에서 서로를 참조하므로 객체의 연관관계를 관리하는 포인트가 2개가 생깁니다.

JPA는 두 객체 연관관계 중에 하나를 정해서 데이터 베이스의 외래키를 관리해야 합니다.

따라서 외래 키를 가지고 있는 테이블과 매핑된 엔티티를 연관관계의 주인으로 정하고 이곳을 통해서만 수정, 삭제 등이 이루어집니다.

주인의 반대편은 외래키에 영향을 주지 않으며 단순 조회만 가능합니다.

다 대 일 [N:1]

다대일 단방향

다대일 단방향

  • 가장 많이 사용하는 연관관계
  • 다대일의 반대는 일대다

다대일 양방향

다대일 양방향

  • 외래 키가 있는 쪽이 연관관계의 주인으로 설정됩니다.
  • 양방향 연관관계는 항상 서로를 참조해야 합니다.
    • 어느 한쪽만 참조되면 양방향 연관관계가 성립되지 않습니다.
    • 연관관계 편의 메소드를 작성하여 양쪽을 한번에 작성하는 것이 좋습니다.
  • 외래키는 "다" 쪽에 두는 것이 올바른 설계입니다.
  • 단방향에서 양방향으로 변경되어도 테이블에 영향을 주지 않습니다.
    • 단순히 객체에서 조회를 할 수 있는 기능을 추가한 것 입니다.

일 대 다 [1:N]

일대다 관계는 엔티티를 하나 이상 참조 가능하므로 자바 컬렉션인 Collection, List, Set, Map 중에 하나를 사용해야합니다.

일대다 단방향 [1:N]

일대다 단방향

  • 일대다 단방향은 일(1)이 연관관계의 주인입니다.
  • 외래키가 다(N)쪽에 있기 때문에 반대편 테이블의 외래키를 관리하는 구조가 됩니다.
  • @JoinColumn을 사용해야합니다.

단점

  • 매핑한 객체가 관리하는 외래키가 다른 테이블에 존재합니다.
    • 연관 관계 처리를 위한 UPDATE SQL을 추가로 실행해야됩니다.
  • 일대다 단방향보다는 다대일 양방향 매핑을 사용해야 합니다.

일대다 양방향

  • 일대다 양방향은 존재하지 않습니다.
  • 이런 경우에는 다대일 양방향을 사용해야합니다.

일 대 일 [1:1]

  • 일대일 관계의 반대도 일대일 입니다.
  • 그러므로 테이블 두 곳 중에 외래 키가 들어갈 곳을 자유롭게 선택할 수 있습니다.
  • 외래 키에는 데이터베이스 유니크(UNI) 제약조건을 추가해야합니다.
  • 다대일과 비슷합니다.
    • 일대일 단방향은 다대일 단방향과 같이 설정하면 됩니다.
    • 일대일 양방향은 다대일 양방향과 같이 설정합니다
      • 연관관계의 주인을 지정하고 반대편에는 mappedby 속성으로 주인을 나타냅니다.

외래키 위치 선택 전략

  • 주 테이블에 외래키
    • 주 객체가 대상 객체의 참조를 가지는 것처럼 주 테이블에 외래 키를 가지고 대상 테이블을 찾습니다.
    • 객체지향 개발자가 선호하며 JPA 매핑이 편리합니다
    • 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
    • 단점: 값이 없으면 외래 키에 null 허용
  • 대상 테이블에 외래키
    • 대상 테이블에 외래 키가 존재
    • 전통적인 데이터베이스 개발자 선호
    • 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
    • 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됨(프록시는 뒤에서 설명

다 대 다 [N:M]

  • 관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없습니다.
    • 그러므로 다대다는 연결 테이블을 추가하여 일대다, 다대일 관계로 풀어내야 합니다.
  • 반면에 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계가 가능합니다.
  • @ManyToMany를 사용하고, @JoinTable로 연결 테이블을 지정합니다.
  • @JoinTable로 연결을 하게되면 연결 테이블이 생성되는데 이는 실무에서 사용하는데 한계가 있습니다.
    • 회원과 상품을 주문하면 연결테이블에 회원_상품 테이블이 생성됩니다.
    • 이곳에는 회원과 상품뿐만 아니라 주문 수량이나 날짜와 같은 추가적인 컬럼이 필요합니다.
    • 컬럼을 추가하게 되면 더이상 @ManyToMany를 사용할 수 없습니다.

결론: 다대다 연관 관계는 연결 테이블용 엔티티를 추가해서 사용합니다

@ManyToMany@OneToMany@ManyToOne으로 나누어서 사용합니다.

'프로그래밍 > JPA' 카테고리의 다른 글

[ JPA ] 연관관계 매핑 기초  (0) 2022.04.13
[ JPA ] 영속성 컨텍스트란?  (0) 2022.03.28
[ JPA ] JPA란?  (0) 2022.03.27