다양한 연관관계 매핑 - 3
"인프런 - 자바 ORM 표준 JPA 프로그래밍 강의를 듣고 작성한 글 입니다."
www.inflearn.com/course/ORM-JPA-Basic#
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 프로그
www.inflearn.com
다대다 연관관계 매핑(N : M)
(사실상 실무에서 쓰지 말라고 하던데....)
객체는 컬렉션을 사용해서 객체 2개로 다대다 연관관계 매핑이 가능하나, 정규화된 테이블은 불가능하다.
즉, 관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다는 뜻이다.
대신 연결 테이블을 하나 추가해서 일대다, 다대일 관계로 풀어내야 한다.
다대다 연관관계는 @ManyToMany 어노테이션을 사용한 다음, @JoinTable 어노테이션을 통해 연결 테이블을 생성하여 매핑할 수 있다.
- Member.java
@ManyToMany
@JoinTable(name = "MEMBER_PRODUCT") // 다대다 연관관계 연결 테이블 생성
private List<Product> product = new ArrayList<>();
- Product.java
@Entity
public class Product {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToMany(mappedBy = "products") // 다대다 연관관계 양방향 매핑 설정
private List<Member> members = new ArrayList<>();
}
위와 같이 코드를 작성하였을 경우 아래와 같은 hibernate SQL 문이 출력되는 것을 볼 수 있다.
Hibernate:
create table MEMBER_PRODUCT ( // 테이블 생성
Member_MEMBER_ID bigint not null,
products_id bigint not null
)
Hibernate:
alter table MEMBER_PRODUCT // 외래 키 유니크 제약 조건 부여
add constraint FKc6hsxwm11n18ahnh5yvbj62cf
foreign key (products_id)
references Product
Hibernate:
alter table MEMBER_PRODUCT // 외래 키 유니크 제약 조건 부여
add constraint FK4ibylolqmostllrjdc147aowv
foreign key (Member_MEMBER_ID)
references Member
편리해 보이지만 다대다 매핑은 한계가 크다.(실무에서 거의 사용하지 않는다고 한다.)
연결 테이블엔 매핑 정보만 들어가고 비즈니스에 필요한 추가 정보를 더 넣을 수가 없다.
또한 연결 테이블이 숨겨져 있기 때문에 SQL 쿼리가 이상하게 나갈 수도 있다.
그렇다면 이 한계를 어떻게 극복할 수 있을까?
-> 연결 테이블용 Entity 를 추가해줄 수 있다.(즉, 연결 테이블을 Entity 로 승격시키는 것이다.)
어노테이션 변화 : @ManyToMany -> @OneToMany, @ManyToOne
- Member.java
/* @ManyToMany
@JoinTable(name = "MEMBER_PRODUCT") // 다대다 연관관계 연결 테이블 생성
private List<Product> product = new ArrayList<>(); */
@OneToMany(mappedBy = "member") // 다대다 연관관계 에서 연결 테이블을 Entity 로 승격시켜서 한계를 해결할 경우
private List<MemberProduct> memberProducts = new ArrayList<>();
- Product.java
/* @ManyToMany(mappedBy = "products") // 다대다 연관관계 양방향 매핑 설정
private List<Member> members = new ArrayList<>(); */
@OneToMany(mappedBy = "product")
private List<MemberProduct> memberProducts = new ArrayList<>();
- MemberProduct.java // Entity 로 승격시킨 연결 테이블 표현
@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;
// 이와 같은 형식으로 연결 테이블을 Entity 로 승격시켜 주면 원하는 정보를 얼마든지 넣어줄 수 있다.
}
* 다대다 연관관계 에서 연결 테이블을 Entity 로 승격해 쓰더라도 테이블의 기본 키는 왠만하면 아무 의미없는 값으로 사용하자.(연결 되어 있는 다른 테이블들의 기본 키들은 외래 키로 활용한다.)