[백견불여일타 스프링 부트 쇼핑몰] 04. 연관관계 매핑 종류
by ymkim01. 연관관계 매핑 종류
- 엔티티들은 대부분 다른 엔티티와 “연관 관계”를 맺고 있다
- 아래 내용을 보면 총 4가지의 연관관계 매핑이 존재
- 일대일(1:1): @OneToOne
- 일대다(1:N): @OneToMany
- 다대일(N:1): @ManyToOne
- 다대다(N:N): @ManyToMany
- 일대일 매핑의 예시
- 쇼핑몰의 회원은 회원 당 하나의 장바구니를 가질 수 있다
- 장바구니 입장에서 보아도 자신과 매핑되는 회원은 한명이다
- 즉, 회원 엔티티와 장바구니 엔티티는 일대일(1:1)의 관계
- 일대다 매핑의 예시
- 하나의 장바구니에는 여러개의 상품이 들어갈 수 있음
- 즉, 장바구니 엔티티와 장바구니 상품 엔티티는 일대다(1:N) 관계
- 두번째로 중요한 부분은 엔티티 매핑 시에는 방향성으로 고려해야 한다
- 테이블은 항상 양방향 연관 관계를 가짐 (PK → FK)
- 객체는 단방향, 양방향이 존재함
02. 일대일 단방향 매핑하기
- 회원 엔티티는 4장에서 만들었기에 장바구니(Cart) 엔티티 생성 후 연관관계 매핑 설정
- 회원(1) → 장바구니(1) → 1:1 관계 지정
- @OneToOne, @ManyToOne → xxxToOne 으로 시작하면 기본이 즉시 로딩(EAGER 전략)
public class Cart {
...
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "member_id")
private Member member;
}
- 즉시 로딩보다는, 지연 로딩을 사용하는 것이 좋다라고 기억이 나는데….
https://ict-nroo.tistory.com/132
03. 다대일 단방향 매핑
package com.shop.domain.cartitem.entity;
import com.shop.domain.cart.entity.Cart;
import com.shop.domain.item.entity.Item;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.*;
@ToString
@Getter
@Setter // 실무에서는 사양 지양
@Table(name = "cart_item")
@Entity
public class CartItem {
/**
* 장바구니에는 고객이 관심 있거나 나중에 사려는 "상품"을 담아 둘 것이다.
* 1. 회원(1)이 상품(N)을 여러개 담을 수 있다
* 2. 하나의 장바구니에는 여러개의 상품이 들어갈 수 있다
* 3. 같은 상품을 여러 개 주문할 수도 있기에 몇 개를 담아 줄 것인지도 설정해야 함
*/
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "cart_item_id")
private Long id;
/* 하나의 "장바구니"에는 여러개의 "상품"을 담을 수 있기에 @ManyToOne 어노테이션 사용 */
@ManyToOne
@JoinColumn(name = "cart_id")
private Cart cart;
/*
장바구니에 담을 상품ㅁ의 정보를 알아야 하기에 상품 엔티티 매핑, 하나의 상품은 여러 장바구니의 장바구니 상품으로
담길 수 있기에 마찬가지로 @ManyToOne 어노테이션 사용
*/
@ManyToOne
@JoinColumn(name = "item_id")
private Item item;
private int count;
}
- Cart, Item 엔티티 사이에 CartItem 엔티티 생성
- CartItem 엔티티
- Cart의 cart_id를 외래키(FK)로 갖는다
- Item의 item_id를 외래키(FK)로 갖는다
- 데이터 등록 예시 → 아래와 같이 데이터가 등록 될 수 있을 듯
- cart_id : 1(홍길동의 장바구니), item_id : 4(곰돌이), count : 3
- cart_id : 1(홍길동의 장바구니), item_id : 2(장갑), count : 4
- cart_id : 1(홍길동의 장바구니), item_id : 7(죽부인), count : 2
04. 다대일/일대다 양방향 매핑
- 양방향 매핑이란 단방향 매핑이 2개 있는 것이라 생각 하면 됨
- 웬만하면 단방향 연관관계 구조를 갖도록 설계를 해야한다
- 양방향 연관관계 사용 시 양쪽 참조가 가능하므로 조회가 간편함
- 하지만 구조가 복잡해지면 양방향 연관관계 사용에 대한 논리적 오류 발생 가능
05. 다대다 매핑
- 실무에서 다대다 연관관계 매핑은 사용하지 않음
- RDBMS(관계형 DB)에서는 정규화된 2개의 테이블을 다대다(N:N)로 표현할 수 없음
- 따라서 연결 테이블을 생성해서 다대다 관계를 일대다(1:N), 다대일(N:1)로 표현해야 함
- 객체는 테이블과 다르게 컬렉션을 사용해서 다대다 관계 표현 가능
- Member Entity
- List_items
- Item Entity
- List_memebers
- Member Entity
- 현재 프로젝트 내에서 다대다 매핑은 사용하지 않지만 코드로 간략히 표현
public class Item {
@ManyToMany
@JoinTable(
name = "member_item",
joinColumns = @JoinColumn(name = "member_id"),
inverseJoinColumns = @JoinColumn(name = "item_id")
)
private List<Member> members;
}
- 다대다 매핑을 사용하지 않는 이유
- 연결 테이블에는 컬럼 추가가 불가능
- 연결 테이블에는 조인 컬럼뿐만 아니라 추가 컬럼들이 필요한 경우가 많음
- 또한 엔티티 조회 시 member 엔티티에서 item을 조회하면 중간 테이블이 있기에 어떤 쿼리가 실행될지 예측하기 쉽지 않음
- 따라서 연결 테이블용 엔티티 하나 생성 후 일대다, 다대일 관계로 표현하면 됨
06. 영속성 전이
- 영속성 전이란 엔티티의 상태를 변경할 때 해당 엔티티와 관련된 엔티티의 상태 변화를 전파시키는 옵션이다.
- 이때 부모는 One에 해당, 자식은 Many에 해당한다
- 예로 Order 엔티티 삭제 시 OrderItem 엔티티가 함께 삭제 되거나, Order 엔티티를 저장 할 때 Order 엔티티에 담겨있던 OrderItem 엔티티를 한꺼번에 저장할 수 있다
CASCADE 종류 설명
PERSIST | 부모 엔티티가 영속화될 때 자식 엔티티도 영속화 |
MERGE | 부모 엔티티가 병합될 때 자식 엔티티도 병합 |
REMOVE | 부모 엔티티가 삭제될 때 연관된 자식 엔티티도 삭제 |
REFRESH | 부모 엔티티가 refresh 되면 자식 엔티티도 refresh |
DETACH | 부모 엔티티가 detach 되면 자식 엔티티도 detach |
ALL | 부모 엔티티의 영속성 상태 변화를 자식 엔티티에 모두 전이 |
07. 고아 객체
- 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 고아 객체라함
- 영속성 전이 기능 사용하면 부모 엔티티를 통해 자식의 생명주기 관리 가능
- 고아 객체 기능은 참조하는 곳이 하나일 때 사용해야 함
- @OneToOne(일대일), @OneToMany(일대다) 에서 사용
08. 지연 로딩
- 엔티티 조회 시 연관된 엔티티를 함께 조회하는 즉시로딩을 알아보자
- 즉시 로딩 이외에도 지연 로딩이라는 Fetch 전략이 존재
'실습 > 백견불여일타 스프링부트 쇼핑몰 프로젝트' 카테고리의 다른 글
[백견불여일타 스프링 부트 쇼핑몰] 03. Spring Security (0) | 2023.04.25 |
---|---|
[백견불여일타 스프링 부트 쇼핑몰] 02. Thymeleaf (0) | 2023.04.25 |
[백견불여일타 스프링 부트 쇼핑몰] 01. Spring Data JPA (0) | 2023.04.25 |
블로그의 정보
기록하고, 복기하고
ymkim