JPA 연관관계 매핑

Haechan Kim·2023년 2월 17일
0

Spring

목록 보기
29/69
post-thumbnail

객체와 관계형 db 테이블이 어떻게 매핑되는지 이해하기!

객채 연관관계와 db 테이블 연관관계 비교

객체db 테이블
참조(주소)로 연관관계 맺음fk로 연관관계 맺음
참조를 사용하는 객체의 연관관계는 단방향db 테이블의 연관관계는 양방향
  • 방향 : 단방향, 양방향
    db 테이블은 외래키 하나로 양쪽 테이블 조인 가능 -> 방향 나눌 필요 없음.
    but 객체는 참조용 필드 있는 객체만 다른 객체 참조 가능.
    두 객체 사이 하나의 객체만 참조용 필드 갖고 참조하면 단방향, 두 객체 모두 각각 참조용 필드 갖고 참조하면 양방향 관계하고 함.

  • 단방향 관계
    회원 객체와 팀 객체의 관계
    회원은 member.team 필드 통해 팀 알 수 있지만 팀 객체로는 소속된 회원 알 수 없음.
    member -> team 조회 가능하지만, team -> member 접근 필드는 없음.

  • 연관 관계 주인
    두 객체 양방향 관계 맺을 때 연관 관계 주인 지정해야 함.
    제어의 권한 갖는 실질적 관계 어떤 것인지 jpa에게 알려줌.
    주인은 두 객체 사이에서 crud할 수 있지만 주인 아니면 조회만 가능.
    주인 아닌 객체에서 mappedBy 속성 사용해 주인 지정.
    tip: fk 있는 곳을 주인으로 정하면 됨!
  • 다중성

  • 일대일 (1:1)

  • 다대일 (N:1)
    post(게시글)와 board(게시판)

@Entity
public class Post {
    @Id @GeneratedValue
    @Column(name = "POST_ID")
    private Long id;

    @Column(name = "TITLE")
    private String title;

    @ManyToOne
    @JoinColumn(name = "BOARD_ID")
    private Board board;
    //...
}
---------------------------
@Entity
public class Board {
    @Id @GeneratedValue
    private Long id;
    private String title;
    
    // 양방향일 경우
    @OneToMany(mappedBy = "board")
    List<Post> posts = new ArrayList<>();
    //... 
}
  • 다대일 단방향
    post에서 board 참조
    N쪽에 @ManyToOne 추가 (N에 fk 있어야 함.)

  • 다대일 양방향
    서로 참조.
    연관 관계 주인이 fk 관리.
    양방향일 경우 @OneToMany 추가하고 연관 관계 주인을 mappedBy로 지정.
    (연관관계의 주인은 mappedBy 사용 x)
    참조 당하는 쪽에서 읽기만 가능.
    외래키 있는 쪽(N)이 연관 관계 주인.

  • 일대다(1:N)
    다대일의 기준은 연관 관계 주인인 다(N) 쪽에 둔 것이고, 일대다의 기준은 연관관계의 주인을 일(1) 쪽에 둔 것.
    일대다(1:N) 단방향은 안쓰는게 좋음.
    대신 객체관계를 조금 포기하고 다대일 양방향 매핑을 사용하자.

  • 다대다 (N:M)

<질문>

  • 왜 일대다(1:N) 단방향은 권장되지 않을까요? 해결 방법은? (* N:1 아님)
    일대다(1:N) 관계는 연관 관계의 기준을 1 쪽에 둔 것이다. 1 쪽이 연관 관계 주인으로 1 쪽 객체에서 다(N) 쪽 객체를 조작(생성,수정,삭제)하는 방법.
    하지만 db 테이블에서는 항상 다(N)쪽에서 외래키를 관리한다.
    객체와 테이블 패러다임 차이 때문에 특이한 구조.
    <단점>
    ex) 팀과 멤버 관계 (1:N)
    팀 엔티티를 수정 시 맴버 테이블에 업데이트 쿼리가 나가는 현상 발생.
    실무에서는 테이블이 수십개가 엮여 있어, 위와 같은 상황은 운영을 힘들게 한다.
    <해결>
    다대일 단방향 또는 양방향을 사용한다. 객체지향적으로 조금 손해 볼 수 있음.
  • 연관 관계의 주인에 대해 설명하고 어떤식으로 지정해야 하는지 설명해주세요.
    두 객체가 양방향 관계(단방향 관계 2개)일 때 연관 관계 주인을 지정해야 한다.
    두 단방향 관계 중 제어의 권한(저장, 수정, 삭제) 갖는 실질적 관계 어떤 것인지 jpa에게 알려주는 것이다.
    주인은 crud 할 수 있지만 주인 아니면 조회만 가능하다.
    외래 키가 있는 곳(다대일일 경우 다)을 연관 관계 주인으로 정하면 된다.

  • 다대다(N:M) 관계는 왜 사용하지 않는 것이 좋을까요? 어떤식으로 해결할 수 있을까요?
    <지양 이유>
    관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계 표현할 수 없고, 연결 테이블 있어야 함.
    jpa에서는 @ManyToMany 어노테이션 사용할 수 있지만 한계 존재한다.
    1) 연결 테이블 생성해 주지만 묵시적으로 생성하기 때문에 예상하지 못한 쿼리 나갈 수 있음.
    2) 연결 테이블 자체에는 매핑 정보만 넣을 수 있고, 추가 데이터를 넣을 수 없음.
    <극복>
    연결 테이블용 엔티티를 추가하여 (연결 테이블을 엔티티로 승격시킴) 일대다, 다대일 관계로 풀어서 사용하는 것이 좋다.

<참고>
https://jeong-pro.tistory.com/231
https://velog.io/@conatuseus/연관관계-매핑-기초-1-i3k0xuve9i
https://jyami.tistory.com/21
https://jdm.kr/blog/141
일대다: https://ym1085.github.io/jpa/JPA-일대다/
다대다: https://ict-nroo.tistory.com/127

0개의 댓글