JPA & QueryDSL

[JPA] 연관 관계 매핑 - @ManyToMany

HSRyuuu 2023. 10. 6. 18:00

JPA 연관관계 매핑의 종류


JPA 연관관계 매핑의 종류는 @ManyToOne, @OneToMany, @OneToOne, @ManyToMany가 있다.

이 글에서는 @ManyToMany 관계에 대해 다룬다.

 

@ManyToMany : 다대다 매핑


RDBMS는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다

따라서 연결 테이블을 추가해서 다대다 관계를 일대다 + 다대일 관계로 풀어내야 한다.

 

결론적으로는 다대다 매핑은 실무에서 사용하지 않는 방법이라고 한다.

 

ManyToMany


 

@ManyToMany 양방향 매핑 example

@Entity
public class Member {
    @Id @GeneratedValue
    private Long id;

    private String username;
    
    @ManyToMany
    @JoinTable(name = "MEMBER_PRODUCT")
    private List<Product> products = new ArrayList<>();
}
@Entity
public class Product {
    @Id @GeneratedValue
    private Long id;
    private String name;
    
    @ManyToMany(mappedBy = "products")
    private List<Member> members = new ArrayList<>();
}

이렇게 매핑을 설정하면 JPA가 자동으로 연결 테이블(MEMBER_PRODUCT)을 만들어준다.

 


다대다 매핑의 한계

  • JPA가 자동으로 연결 테이블을 생성하지만 해당 쿼리가 예측하기 어렵다.
  • 비즈니스 로직을 위한 정보들이 해당 연결 테이블에 들어가야 하지만
    JPA가 만든 연결테이블에는 다른 컬럼을 추가할 수 없다.

다대다 매핑의 한계 극복 방법

연결 테이블 용 엔티티를 추가한다.

예를 들어 Member(이용자)와 Product(상품) 사이에 MemberProduct라는 엔티티를 추가한다.

해당 MemberProduct 엔티티에서 Member와 Product를 FK로 가지며, 다른 부가 정보들을 추가할 수 있다. 

 

연결 테이블 용 엔티티

@Entity
public class MemberProduct {

    @Id @GeneratedValue
    private Long id;

    @ManyToOne
    @JoinColumn(name = "MEMBER_ID")
    private Member member;

    @ManyToOne
    @JoinColumn(name = "PRODUCT_ID")
    private Product product;

    private int amount;
    private int price;

    private LocalDateTime orderDateTime;
}

MemberProduct는 MEMBER_ID와 PRODUCT_ID를 FK로 가지게 되고, 각각 ManyToOne으로연관관계의 주인이 된다.  

@Entity
public class Member {
    @Id @GeneratedValue
    private Long id;
    private String username;

    @OneToMany(mappedBy = "member")
    private List<MemberProduct> memberProducts = new ArrayList<>();
}

Member는 MemberProduct의 member와 매핑된다.

@Entity
public class Product {
    @Id @GeneratedValue
    private Long id;
    private String name;

    @OneToMany(mappedBy = "product")
    private List<MemberProduct> memberProducts = new ArrayList<>();
}

Product는 MemberProduct의 product와 매핑된다.

 

이후에 이 MemberProduct의 이름을 비즈니스 상황에 맞게 변경하면 된다.

이 상황에서는 이용자가 상품을 주문한다면 MemberProduct를 Order로 변경하여 의미를 부여할 수 있다.

 

다대다 매핑의 한계 극복

 


(참고) 인프런 - 김영한 님 '자바 ORM 표준 JPA 프로그래밍 - 기본 편'
https://www.inflearn.com/course/ORM-JPA-Basic