👣 개요
해당 게시물에서는 '다대일', '일대다', '일대일', '다대다' 의 연관관계를 다룰 예정이었다.
하지만 앞선 5장과 다소 중복이 많기 때문에 '다대다' 관계에 대해서만 다루고 넘어갈 것이다.
👣 다대다 연관관계
마치 쇼핑몰 웹사이트에서의 '회원'과 '상품'의 관계와 같다.
이하, '회원'을 A로 '상품'을 B로 표기한다.
A는 여러 개의 B를 소유할 수 있다. 마찬가지로 B는 여러 명의 A에 의해서 주문되어 진다.
안타깝게도 SQL에서는
정규화가 진행된 테이블 2개만으로 이 관계를 정의할 수 없다.
때문에 A와 B 사이에 '주문 테이블'[이하 C]가 추가적으로 필요하다.
이를 통해 A-C 혹은 B-C의 관계를 다시 '다대일'관계로 만들어서 사용할 수 있다.
create table MEMBER (
ID bigint primary key,
USERNAME varchar(100)
);
create table PRODUCT (
ID bigint primary key,
NAME varchar(100)
);
create table MEMBER_PRODUCT (
MEMBER_ID bigint,
PRODUCT_ID bigint,
primary key (MEMBER_ID, PRODUCT_ID),
foreign key (MEMBER_ID) references MEMBER(ID),
foreign key (PRODUCT_ID) references PRODUCT(ID)
);
하지만 OOP에서는
객체 2개로도 다대다 관계를 정의할 수 있다.
단순히 클래스의 필드에 List<?> 타입를 할당하기만 하면 그만이기 때문이다.
때문에 엔티티를 매핑할 때, 단순히 List<?> 타입 필드 위에 @ManyToMany 어노테이션만
부여하면 된다.
public class Member {
private Long id;
private String username;
private List<Product> products;
}
public class Product {
private Long id;
private String name;
private List<Member> members;
}
당연히 SQL과 OOP와의 간극을 해결하기 위해 @JoinTable이라는 어노테이션을 추가로
부여해야 한다.
👣 연관관계 매핑 어노테이션
@ManyToMany
모든 속성은 orphanRemoval가 없다는 것을 제외하면 @OneToMany와 같다.
@JoinTable
엔티티로 명시하지 않았지만 다대다 관계를 정의하기 위한 추가 테이블을
알아서 정의하는 어노테이션.
간단하게 FK로만 이뤄진 2개의 칼럼으로 구성된 테이블을 생성한다.
- name
연결 테이블의 이름을 지정한다. - joinColumns
현재 엔티티의 칼럼 중 JoinTable의 FK로 사용할 칼럼을 지정. - inverseJoinColumns
상대 엔티티의 칼럼 중 JoinTable의 FK로 사용할 칼럼을 지정.
결국, [다대다 연관관계]에서 제시한 엔티티는 다음과 같이 매핑할 수 있다.
@Entity @Table(name = "MEMBER")
public class Member {
@Id
private Long memId;
private String username;
@ManyToMany
@JoinTable(
name = "MEMBER_PRODUCT",
joinColumns = @JoinColumn(name = "mem_id"),
inversejoinColumns = @JoinColumn(name = "pro_id")
)
private List<Product> products;
}
@Entity @Table(name = "PRODUCT")
public class Product {
@Id
private Long proId;
private String name;
@ManyToMany(mappedBy = "products")
private List<Member> members;
}
👣 JoinTable의 한계
사실, 편의를 위해서 @JoinTable을 사용하는 거지
실제로 적용하기 위해서는 그냥 직접 Member_Product 엔티티를 만드는 것이
유지보수에 유리하다. 이유는 다음과 같다.
1. JoinTable에 추가적인 칼럼[생성일자, 거래가격 등]을 생성하면
적용할 수 없다.
2. 식별 관계가 강제되므로 인조 키를 사용할 수 없다.
위와 같은 이유로 그냥 직접 테이블을 만들어서 2개의 다대일 관계로 매핑하는 것이
뒷탈이 없다.
'JPA' 카테고리의 다른 글
8장 프록시와 연관관계 관리 (0) | 2023.08.31 |
---|---|
7장 고급 매핑 (0) | 2023.08.31 |
5장 연관관계 매핑 기초 (0) | 2023.08.30 |
4장 엔티티 매핑 (0) | 2023.08.30 |
3장 영속성 관리 (0) | 2023.08.27 |