본문 바로가기
강의 정리/자바 ORM 표준 JPA

5. 다양한 연관관계 매핑

by 이석준석이 2020. 12. 28.

1. 다대일 [N:1]

  • 다(N)가 연관관계 주인인 경우
    • 가장 많이 사용되는 연관관계
    • @ManyToOne + @JoinColumn

2. 일대다 [1:N]

  • 일(1) 이 연관관계의 주인인 경우
  • @OneToMany + @JoinColumn (@JoinColumn 이 없으면 조인테이블 방식을 사용하게 된다.)

2.1. 일대다 단방향

 

객체 관점

  • 아래의 그림을 보면, Team 에서 Member 로 가는 참조가 있다.

테이블 관점

  • FK 는 어쩔 수 없이 다(N) 쪽에 있다.

 

일전에 고려했던 넌센스한 문제가 생긴다.

  • Team.members.add(member) 을 하면
  • Member 테이블에 있는 FK 가 변경된다.

Team 객체에 변경을 가했는데, 데이터베이스 관점에서는 Member 테이블이 갱신되는 문제.

 

추가적으로 Team에 Member를 추가하면, Member 테이블을 갱신해야하므로

  • update 쿼리를 한개 더 날려야 한다.

웬만하면, 일대다 단방향 보다는 다대일 양방향을 사용하는 것이 좋다.

 

2.2. 일대다 양방향

  • 공식적으로 지원하지 않음.
  • 반대 방향에서 읽기 전용으로
    • @ManyToOne을 사용하고, @JoinColumn(insertable = false, updatable = false)

쓰지말고, 다대일 양방향을 사용하자.


3. 일대일 [1:1]

 

  • 주 테이블 / 대상 테이블 어디에나 외래 키를 넣을 수 있다.
  • 외래키에 Unique 제약조건을 추가해줘야 한다.

3.1. 주 테이블 FK 전략

  • 다대일과 비슷하다.
단방향 양방향
Member {
     @OneToOne + @JoinColumn
     private Locker locker;
}
단방향  + 

Locker {
     @OneToOne(mappedBy = "locker")
     private Member member;
}

 

3.2. 대상 테이블 FK 전략

단방향 (지원하지 않음) 양방향
  Locker.java 를 주인으로, Member.java 를 읽기 전용으로 한다.

위의 주 테이블 FK 양방향 전략과 반대로 설정하면 된다.

 

  • 하나의 회원이 여러개의 Locker 를 가질 수 있는 Rule 이 생기거나, Locker 하나에 여러명의 멤버가 사용할 수도 있는 점,
  • 멤버에 Locker를 넣으면 더 편하다는 점 (멤버는 웬만하면 조회하니까) 등 등을 조회해서 선택해야 한다.

 

주 테이블에 외래키

  • 객체지향 개발자가 선호
  • 장점 : 주 테이블 조회를 통해 대상 테이블에 데이터를 확인할 수 있다.
  • 단점 : 값이 없으면 외래 키에 null 을 허용하게 된다.

대상 테이블에 외래키

  • DB 개발자가 선호
  • 장점 : 주 테이블 : 대상 테이블 관계 (1:1) 를 1:N 으로 변경 시, 데이터베이스 구조가 유지됨
  • 단점 : 지연 로딩으로 설정해도, 항상 즉시 로딩됨

4. 다대다 [N:N]

 

  • 실무에서는 써서는 안된다.
  • 연결 테이블을 추가해서
    • 다대다 -> 일대다 + 다대일 로 풀어야 한다.
  • @ManyToMany + @JoinTable 로 연결테이블 지정
  • 양방향은 + @ManyToMany(mappedBy)
@Entity
public class Member {

...

    @ManyToMany
    @JoinTable(name = "MEMBER_PRODUCT") // joinColumns, inverseJoinColumns
    private List<Product> products = new ArrayList<>();

...
}

@Entity
public class Product {
...
    @ManyToMany(mappedBy = "products")
    private List<Member> members = new ArrayList<>();
...
}
Hibernate: 
    
    create table MEMBER_PRODUCT (
       Member_MEMBER_ID bigint not null,
        products_PRODUCT_ID bigint not null
    )

 

페러다임의 불일치

  • 객체 : 다대다 가능
  • 테이블 : 다대다 불가능

 

@ManyToMany 는

  • 매핑 정보까지는 넣을 수 있으나, 추가 컬럼을 넣을 수 없다.
  • 쿼리도 중간 테이블이 숨겨져있기 때문에, 내가 생각하지 못한 쿼리가 나갈 수 있다.

 

'강의 정리 > 자바 ORM 표준 JPA' 카테고리의 다른 글

7. 프록시와 연관관계 관리  (0) 2021.01.01
6. 고급 매핑  (0) 2020.12.29
4. 연관관계 매핑 기초  (0) 2020.12.27
3. 엔티티 매핑  (0) 2020.12.27
2. 영속성 관리  (0) 2020.12.26