2024.10.07 - [Spring Framework/Spring Boot] - 도메인 모델과 테이블 설계
* 테이블 설계
* Member 엔티티 - 회원 정보 저장
@Column(name="member_id")
JPA에서 필드와 DB 테이블의 컬럼을 매핑할 때 사용하는 어노테이션이다.
Member 테이블의 id 필드는 Order 테이블의 member_id(외래키)라는 컬럼과 연결된다.
@Embedded
JPA에서 내장 타입을 나타내는 어노테이션이다.
이 필드가 다른 엔티티 클래스처럼 별도의 테이블에 매핑되지 않고 해당 엔티티의 일부로서, 같은 테이블에 포함된다.
Address는 별도의 테이블인 독립적 엔티티가 아닌, Member 테이블의 일부이다.
@OneToMany
Member 테이블과 Order 테이블이 일대다 관계를 가진다. 회원 한 명은 여러 개의 주문을 가질 수 있다.
(mappedBy="member")
어떤 필드가 연관관계의 주인인지, 어느 필드가 연관 관계를 매핑하는 역할을 하는지 하는 데 사용된다.
member는 Order(주문) 테이블에 있는 필드 중 하나이며, 이 필드가 연관관계의 주인이다.
List<Order> orders
회원(Member)과 관련된 주문(Order)들의 목록을 나타낸다. 회원이 주문을 하면 orders 리스트에 Order 객체가 추가된다.
여러 개의 Order 객체를 저장하기 위해 List<Order>을 사용했다.
new ArrayList<>()
주문 내역이 없는 상태에서 주문을 조회하면 에러가 발생할 수 있다.
즉, null 상태에서 발생할 수 있는 오류를 방지하기 위해 빈 리스트로 초기화해 둔다.
* Order 엔티티 - 주문 정보 저장
@Entity
@Table(name = "orders")
@Getter @Setter
public class Order {
@Id @GeneratedValue
@Column(name = "order_id")
private long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member; // 주문 회원
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "delivery_id")
private Delivery delivery; // 배송 정보
private LocalDateTime orderDate; // 주문 시간
@Enumerated(EnumType.STRING)
private OrderStatus status; // 주문 상태(ORDER/CANCEL)
// 연관관계 메서드
public void setMember(Member member) {
this.member = member;
member.getOrders().add(this);
}
public void addOrderItem(OrderItem orderItem) {
orderItems.add(orderItem);
orderItem.setOrder(this);
}
public void setDelivery(Delivery delivery) {
this.delivery = delivery;
delivery.setOrder(this);
}
}
@Table(name="orders)
Order 엔티티가 orders 테이블과 매핑된다.
테이블명이 클래스명과 다르기 때문에 @Table을 사용해 명시적으로 설정하였다.
@JoinColumn(name="member_id")
JPA에서 외래키를 지정하는 어노테이션이다.
member_id는 외래키로 사용되어 orders 테이블(현재 엔티티)에서 member 테이블(Member 엔티티) 연결된다.
@Column | @JoinColumn | |
사용 목적 | 필드와 DB 컬럼을 단순 매핑 | 엔티티 간 연관 관계를 설정할 때 외래키 정의 및 매핑 |
매핑 | 엔티티의 단순 필드를 DB의 컬럼과 연결 | 외래키로 사용될 컬럼을 정의하고 다른 엔티티와 연결 |
@JoinColumn | mappedBy | |
사용 대상 | 연관 관계 주인 엔티티에서 사용 | 연관 관계 비주인 엔티티에서 사용 |
외래키 관리 | 외래키를 직접 관리 | 외래키를 관리하지 않고 연관된 주인 엔티티에서 참조 |
연관 관계 설정 | 어느 컬럼이 외래키로 사용될지 지정 | 연관 관계의 주인이 되는 필드 지정 |
작동 방식 | 외래키를 통해 연관 관계 설정 | 주인 엔티티의 필드로 관계 매핑 |
@JoinColumn(name="delivery_id")
현재 엔티티(Order)에서 다른 엔티티(Delivery)와 delivery_id 외래키로 관계를 가진다.
orders 테이블에는 delivery_id라는 컬럼이 존재하며, 이 컬럼은 delivery 테이블의 기본키(id)를 참조하는 외래키가 된다.
→ 특정 주문에 대해 해당 주문의 배송 정보를 참조할 수 있다.
@Enumerated(EnumType.STRING)
JPA에서 열거형(enum) 타입의 필드를 어떻게 DB에 저장할 것인지 지정하는 어노테이션이다.
EnumType.STRING은 enum의 이름을 문자열로 DB에 저장한다.
* OrderStatus 엔티티 - 주문 상태 정보
* OrderItem 엔티티 - 주문 상품 정보
fetch = FetchType.LAZY
성능 최적화를 위한 관련된 엔티티를 실제로 사용할 때만 조회하여 불필요한 DB접근을 줄이는 전략이다.
지연 로딩(Lazy Loading)을 사용하여 연관된 Item 객체를 실제로 사용할 때만 조회한다.
모든 연관관계는 지연로딩으로 설정해야한다.
- 즉시 로딩(EAGER)은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵다.
- 실무에서 모든 연관관계는 지연로딩(LAZY)으로 설정해야 한다.
- 연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용한다.
- @XToOne(OneToOne, ManyToOne) 관계는 기본이 즉시 로딩이므로 직접 지연로디으로 설정해야한다.
* Item 엔티티 - 상품 정보
@Inheritance(strategy=)
JPA에서 엔티티 상속 구조를 DB에 어떻게 저장할지 결정하는 상속 전략 방식이다.
InheritanceType.SINGLE_TABLE)
상속된 모든 엔티티를 하나의 테이블에 저장하는 방식이다.
단일 테이블 전략은 모든 상속된 엔티티가 하나의 테이블의 저장되므로 조인이 필요 없고 성능이 빠르지만, 비어있는 컬럼이 많이 생길 수 있다.
만약 각 상품(item)들마다 별도의 테이블을 생성한 조인 전략을 사용했다면, 테이블 수가 늘어나고 복잡한 조인 연산이 자주 발생하기에 단일 테이블 전략을 사용한 것이다.
@DiscriminatorColumn(name="dtype")
상속 구조에서 엔티티 타입을 구분하는 컬럼을 지정하는 어노테이션이다.
dtype이라는 컬럼이 테이블에 추가되며, 이 컬럼을 통해 어떤 엔티티가 저장되었는지 구분한다.
예를 들어, Book, Movie, Album 등과 같은 하위 아이템들이 dtype 값으로 구분된다.
* Album, Book, Movie 엔티티
@DiscriminatorValue
상속구조에서 상위 엔티티 테이블(단일 테이블)에 구체적인 엔티티를 구분할 때 사용되는 값을 지정한다.
* Delivery 엔티티 - 배송 정보
* DeliveryStatus 엔티티 - 배송 상태 정보
* Category 엔티티 - 카테고리 정보
@JoinTable
다대다 관계를 풀기 위해 중간 테이블을 설정한다.
중간 테이블은 category_item이라는 테이블로, 두 엔티티 간의 관계를 관리한다.
- joincolumns : 현재 엔티티(Category)의 외래키(category_id)를 지정
- inverseJoinColumns : 상태방 엔티티(Item)의 외래키(item_id)를 지정
JoinColumn(name="parent_id")
DB에서 부모 카테고리의 외래키(parent_id)와 연결된다.
* DB 확인
테이블이 설계한 대로 잘 생성되었다.
끝.
'Spring Framework > Spring Boot' 카테고리의 다른 글
[Spring Boot] 쇼핑몰 #5 - 상품 도메인 개발 (0) | 2024.10.12 |
---|---|
[Spring Boot] 쇼핑몰 #4 - 회원 도메인 개발 (4) | 2024.10.11 |
[Spring Boot] 쇼핑몰 #2 - 도메인 모델과 테이블 설계 (2) | 2024.10.07 |
[Spring Boot] 쇼핑몰 - 환경설정(View, H2 Database, JPA) (1) | 2024.10.05 |
[Spring Boot] REST API - PUT (+ Talend API Tester) (0) | 2024.07.14 |
댓글