다대다 관계의 경우 그대로 사용하지 못하고 반드시 정규화를 통해 중간 테이블을 만들어줘야 한다.

 

이러한 관계가 있을 때 반드시 중간 중간 테이블을 두어 일대다+다대일 형태로 변형해줘야 한다.

 

 

JPA에서는 @ManyToMany를 통해 연관관계를 매핑할 경우 하이버네이트가 위와 같은 중간 테이블을 알아서 만들어서 처리해준다.

@Entity
public class Member {

    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    @ManyToMany
    @JoinTable(name = "새로 만들어줄 중간 테이블 이름")
    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<>();
}

위와 같이 @ManyToMany로 양방향 매핑 되어있을 때 (굳이 양방향이어야 할 필요는 없음. 단방향이어도 괜찮다) Member의 @JoinTable(name = "새로운 테이블 명")을 통해 중간 테이블을 따로 만들어준다.

 

하지만 이러한 방식은 실무에서 절대로 사용하면 안 된다.

 

중간테이블을 만들고 PK, FK 쌍을 알아서 매핑해주는 것 까지는 문제가 없는데, 실무 레벨에서는 이러한 테이블 매핑에 필요한 필수적인 정보들 외에도 중간 테이블이 가져야하는 여러 가지 컬럼들이 있을 수 있다.

(예를들어 멤버 - 오더 - 상품 이렇게 되어있을 경우 오더가 발생한 시간이라든가 하는 정보들)

 

하이버네이트에 의해 생성된 중간 테이블은 관계 설정에 필수적으로 필요한 정보들만 담겨있을 뿐 이러한 비즈니스 로직상 필요한 정보들은 담기지 않는다.

 

따라서, 실무 단계에서는 @ManyToMany는 절대 사용하지 말아야 한다.

 

다대다 관계를 사용하고 싶은 경우라면 중간 테이블에 대한 클래스를 직접 만들어서 @ManyToOne과 @OneToMany의 조합을 만들어 사용해야 한다.

 

 

 

중간 테이블을 직접 만들어서 관계를 매핑하면 아래와 같은 형태가 된다.

@Entity
public class Member {

    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    @OneToMany(mappedBy = "member")
    private List<MemberProduct> memberProducts = new ArrayList<>();
}
.
.
.
@Entity
public class Product {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @OneToMany(mappedBy = "product")
    private List<MemberProduct> memberProducts = new ArrayList<>();
}
.
.
.
@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;
}

Member(ONE) - (MANY)MemberProduct(MANY) - (ONE)Product

 

MemberProduct는 Order 정도의 역할이 되겠다.

 

 

 

중간 테이블을 하나의 엔티티 개념으로 사용하면 (MemberProduct -> Order) 이러한 형태를 가질 수 있게 된다.

(ORDER_ID는 Generated Value로 주어진 비즈니스적 의미를 갖지 않는 값)

 

 

 

+ Recent posts