오늘은 다대다 연관관계를 살펴보겠습니다.
Member는 Product 리스트를 들고있고
Product도 Member 리스트를 가지고 있는 아래와 같은 상황입니다.
객체는 위와 같이 서로가 서로의 리스트를 가지고 있을 수 있지만
관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.
진짜 이 말이 맞는지 코드를 작성하고 확인해 보도록 하겠습니다.
Member entity를 작성합니다.
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
private String username;
@ManyToMany
@JoinTable(name = "MEMBER_PRODUCT")
private List<Product> products = new ArrayList<>();
}
Product entity를 작성합니다.
@Entity
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToMany(mappedBy = "products")
private List<Member> members = new ArrayList<>();
}
h2 database에 접속을 하면 아래와 같이 데이터 베이스가 생성된 것을 확인할 수 있습니다.
다대다 관계를 아래와 같이 풀어냈다고 볼 수 있습니다.
테이블 두개로 풀어내지는 못하였지만 중간에 연결 테이블을 두면서 구현이 되는 모습입니다.
그냥 사용하면 될까요?
편리해 보이지만 실무에서는 사용할 수 없습니다.
맵핑 정보만 들어가고 중간 테이블에 추가적인 정보를 넣을 수가 없습니다. (실무에서는 중간 테이블에 추가적인 정보가 들어가는 경우가 많습니다)
Membe와 Product를 join을 하면 쿼리가 이상하게 나갑니다. (중간 테이블이 숨겨져 있기 떄문입니다.)
연결 테이블이 단순히 연결만 하고 끝나지 않기 때문입니다.
@ManyToMany -> @OneToMany, @ManyToOne 관계로 변경해보자.
연결 테이블을 엔티티로 승격
@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 orderAmount;
private LocalDateTime orderDate;
}
상품 엔티티는 아래와 같이 변경할 수 있습니다.
@Entity
public class Product {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "product")
private List<MemberProduct> memberProducts = new ArrayList<>();
}
사용자 엔티티는 아래와 같이 변경할 수 있습니다.
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
private String username;
@OneToMany(mappedBy = "member")
private List<MemberProduct> memberProducts = new ArrayList<>();
}
제약조건을 걸때는 아래와 같이 사용하는 것이 좋지만 운영을 하면서 계속해서 발전하다 보면 id가 종속되는 경우도 존재한다고 합니다.
아래와 같은 테이블 구조를 만들었는데 위와 같은 상황이 발생한다면 시스템을 유연성있게 갈아치우는게 쉽지가 않다고 합니다.
그렇다면 어떻게 해야 할까요?
김영한 선생님 께서는 결국 아래와 같이 테이블 구조를 만들고 사용을 하는 것이 좋다고 합니다.
추상적인 말이지만, 경험을 통해서 아래와 같이 코드를 만드는게 실무적으로 도움이 되는 경우가 더 많았다고 합니다.
오늘은 다대다 테이블을 일대다, 다대일로 풀어내는 것 까지 알아보았습니다.
다음에는 이렇게 만든 테이블을 이용해보고 문제가 발생하는지, 발생하지 않는지 조금 더 알아보는 시간을 가져보도록 하겠습니다.
'공부방 > Spring' 카테고리의 다른 글
스프링 프레임워크의 등장 배경 (0) | 2023.04.23 |
---|---|
[Mysql] order by, group by (0) | 2023.01.10 |
deleteById, deleteByName (0) | 2022.09.30 |
[오류] FK가 PK가 아닌 다른 컬럼과 연관관계가 있을 때 (0) | 2022.08.31 |
[JPA] PK가 아닌 필드를 참조하는 FK를 만들 때 (0) | 2022.08.31 |