본문 바로가기
혼자 공부하는 것들/JPA

[지구최강 JPA 스터디] 6-7주차 연관관계 매핑 4가지와 단방향, 양방향!

by applepick 2022. 8. 14.
반응형

사실 테이블에서 방향이라는 개념은 따로 있지 않고 설계의 편의를 위해 적용

테이블이 한쪽만 참조하면 단방향이고, 테이블이 양쪽에서 참조하면 양방향입니다.

양방향에서 연관관계 주인이 중요합니다. 양방향 매핑에서 연관관계 주인은 외래 키를 관리하는 곳

연관관계 주인의 반대편은 외래키에 영향을 주지 않습니다. 단순 조회 가능

단방향은 연관관계 주인이라는 개념이 따로 없습니다.

JPA에서 연관관계 매핑 방식이 4가지가 있습니다.

다대일 : @ManyToOne

외래 키가 있는 쪽이 연관관계 주인입니다.

다대일에서도 단방향과 양방향을 설계할 수 있습니다.

축구선수와 팀의 테이블을 설계해야 한다면 축구선수 테이블이 @ManyToOne입니다.(연관관계 주인은 축구선수 테이블) = [단방향]

축구선수 여러 명은 하나의 팀에 속할 수 있습니다. 여기서 팀에서 축구선수를 조회하고 싶다면 팀 테이블에 @OneToMany를 넣어준다면 양방향으로 만들 수 있습니다. [양방향]

 

일대다 : @OneToMany

일대다 단방향은 1:N에서 1이 연관관계 주인입니다. 테이블 일대다 관계는 항상 N 쪽에 외래 키를 가지게 됩니다.

객체와 테이블의 차이로 인해 반대편 테이블의 외래 키를 관리하는 특이한 구조를 가지고 있습니다. 일대다 같은 경우 @JoinColumn을 꼭 사용해야 합니다. 그렇지 않은 경우 JPA에서 중간 조인 테이블을 생성해서 사용합니다. 단점으로는 일대다 단방향은 엔티티가 관리하는 외래 키가 다른 테이블에 있어 불편합니다. 따라서 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하면 좋을 것 같습니다.(위에 예시 참조)

 

일대다 양방향은 JPA에서 공식적으로 존재하지는 않지만 @JoinColumn(insertable=false, updatable=false)를 사용해서 읽기 전용 필드를 사용해서 사용할 순 있지만, 다대일 양방향을 사용하면 좋을 것 같습니다.

 

일대일 :  @OneToOne

일대일 관계는 반대편도 일대일 관계를 가지고 있습니다. 주 테이블이나 대상 테이블에 외래 키를 지정할 수 있습니다.

주 테이블에 외래 키

  • 객체가 대상 객체의 참조를 가지는 것처럼
주 테이블에 외래 키를 두고 대상 테이블을 찾음
  • 장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능
  • 단점: 값이 없으면 외래 키에 null 허용

대상 테이블에 외래 키

  •  테이블에 외래 키가 존재
  • 장점: 주 테이블과 대상 테이블을 일대일에서 일대다 관계로 변경할 때 테이블 구조 유지
  • 단점: 프록시 기능의 한계로 지연 로딩으로 설정해도 항상 즉시 로딩됩니다.

외래 키에 데이터베이스 유니크 제약조건을 추가합니다.

제가 나이키를 좋아하니 나이키로 예를 들어보겠습니다. 나이키에서는 유니크한 신발을 판매하는 경우 응모를 통해 추첨으로 신발을 살 수 있는 권한을 줍니다. 이때 비즈니스 적으로 하나의 유저에 하나의 물품으로 응모권은 한 번만 신청할 수 있습니다. 이럴 경우 1(유저):응모권(1) 즉, 일대일 관계가 성립됩니다. 응모권에서도 유저를 확인할 수 있고, 유저에게서도 응모권을 확인할 수 있습니다. 다대일 양방향 매핑처럼 외래 키가 있는 곳이 연관관계의 주인이 됩니다. 반대편은 mappedBy를 적용하면 됩니다.

일대일 단방향 매핑은 JPA에서 지원해주지 않습니다.

 

다대다 : @ManyToMany

다대다는 잘 사용하지 않으나 비즈니스적으로 필요하다면 @OneToMany와 @ManyToOne으로 풀어 적용해봅니다. 연결 테이블을 엔티티로 만들어 연관테이블 -> 엔티티(연결테이블) <- 연관테이블로 설계해서 풀면 좋을 것 같습니다. 이때 연결 테이블 설계 시 두 가지 방법이 있습니다. 연결테이블 자체 pk를 가져가는 방식과 두 연관테이블의 pk를 연결테이블의 pk로 가져가는 방식이 있습니다. 어느것이 좋다라고 단정지을순없지만, 유연한 변경성과 알아보기 쉽도록 저는 연결테이블 자체로 pk를 설정하여 쓰는 방식을 사용할 것 같습니다.

반응형

댓글