요구사항 분석
- 회원 기능
- 회원 등록
- 회원 조회
- 상품 기능
- 상품 등록
- 상품 수정
- 상품 조회
- 주문 기능
- 상품 주문
- 주문 내역 조회
- 주문 취소
- 기타 요구사항
- 상품의 종류는 도서, 음반, 영화가 있다.
- 상품을 카테고리로 구분할 수 있다.
- 상품 주문 시 배송 정보를 입력할 수 있다.
도메인 모델 설계
- 요구사항을 분석해서 설계한 도메인 모델
- 회원, 주문, 상품의 관계
회원은 여러 상품을 주문할 수 있음
한 번 주문할 때 여러 상품을 선택할 수 있으므로 주문과 상품은 다대다 관계
다대다 관계는 관계형 데이터베이스는 물론이고 엔티티에서도 거의 사용하지 않으므로
주문상품이라는 엔티티를 추가해서 다대다 관계를 일대다, 다대일 관계로 풀어냄 - 상품 분류
상품은 도서, 음반, 영화로 구분되는데 상품이라는 공통 속성을 사용하므로 상속 구조로 표현
- 회원, 주문, 상품의 관계
- 엔티티 분석
- 회원 (Member)
이름(name)과 주문한 상품들(orders) 그리고 임베디드 타입인 주소(Address)를 가짐 - 주문 (Order)
한 번 주문 시 여러 상품을 주문할 수 있으므로 주문과 주문상품은 일대다 관계
주문은 상품을 주문한 회원(member)과 배송 정보(delivery), 주문 날짜(orderDate), 주문 상태(status)를 가지고 있음
주문 상태는 열거형을 사용해 주문, 취소를 표현할 수 있음 - 주문상품 (OrderItem)
주문한 상품 정보가 주문 금액(orderPrice), 주문 수량(count) 정보를 가지고 있음 - 상품 (Item)
이름(name), 가격(price), 재고수량(stockQuantity)을 가지고 있음
상품을 주문하고 재고수량이 줄어들고, 상품의 종류로는 도서, 음반, 영화가 있으며 각각은 사용하는 속성이 조금씩 다름 - 배송 (Delivery)
주문 시 하나의 배송 정보를 생성함
주문과 배송은 일대일 관계 - 카테고리 (Category)
상품과 다대다 관계를 맺음 - 주소 (Address)
값 타입(임베디드 타입)이며 회원과 배송에서 사용
- 회원 (Member)
테이블 설계
- 객체 도메인 모델을 매핑하기 위해 설계한 테이블
- MEMBER
회원 엔티티의 Address 임베디드 타입 정보가 회원 테이블에 그대로 들어가며
DELIVERY 테이블도 마찬가지 - ITEM
앨범, 도서, 영화 타입을 통합해서 하나의 테이블로 만들었으며 DTYPE 컬럼으로 타입을 구분
- MEMBER
연관관계 정리
- 연관관계를 어떻게 매핑했는지 정리
- 회원과 주문
일대다 양방향 관계이므로 외래 키가 있는 주문이 연관관계의 주인
그러므로 Order.member를 ORDERS.MEMBER_ID 외래 키와 매핑 - 주문상품과 주문
다대일 양방향 관계이므로 주문상품이 연관관계의 주인
그러므로 OrderItem.order를 ORDER_ITEM.ORDER_ID 외래 키와 매핑 - 주문상품과 상품
다대일 단방향 관계이므로 OrderItem.item을 ORDER_ITEM.ITEM_ID 외래 키와 매핑 - 주문과 배송
일대일 양방향 관계이므로 Order.delivery를 ORDERS.DELIVERY_ID 외래 키와 매핑 - 카테고리와 상품
@ManyToMany를 사용해서 매핑
- 회원과 주문
엔티티 클래스
- 회원 엔티티
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
@Embedded
private Address address;
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<Order>();
// Getter, Setter
...
}
- 주문 엔티티
@Entity
@Table(name = "ORDERS")
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<OrderItem>();
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "DELIVERY_ID")
private Delivery delivery; // 배송정보
private Date orderDate; // 주문시간
@Enumerated(EnumType.STRING)
private OrderStatus status; // 주문상태
//==연관관계 메소드==//
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);
}
// Getter, Setter
...
}
- 주문상품 엔티티
@Entity
@Table(name = "ORDER_ITEM")
public class OrderItem {
@Id @GeneratedValue
@Column(name = "ORDER_ITEM_ID")
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ITEM_ID")
private Item item; // 주문 상품
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "ORDER_ID")
private Order order; // 주문
private int orderPrice; // 주문 가격
private int count; // 주문 수량
// Getter, Setter
...
}
- 상품 엔티티
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
public abstract class Item {
@Id @GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name; // 이름
private int price; // 가격
private int stockQuantity; // 재고수량
@ManyToMany(mappedBy = "items")
private List<Category> categories = new ArrayList<Category>();
// Getter, Setter
...
}
- 상품 - 도서 엔티티
@Entity
@DiscriminatorValue("B")
public class Book extends Item {
private String author;
private String isbn;
// Getter, Setter
...
}
- 상품 - 음반 엔티티
@Entity
@DiscriminatorValue("A")
public class Album extends Item {
private String artist;
private String etc;
// Getter, Setter
...
}
- 상품 - 영화 엔티티
@Entity
@DiscriminatorValue("M")
public class Movie extends Item {
private String director;
private String actor;
// Getter, Setter
...
}
- 배송 엔티티
@Entity
public class Delivery {
@Id @GeneratedValue
@Column(name = "DELIVERY_ID")
private Long id;
@OneToOne(mappedBy = "delivery")
private Order order;
@Embedded
private Address address;
@Enumerated(EnumType.STRING)
private DeliveryStatus status; // ENUM [READY(준비), COMP(배송)]
// Getter, Setter
...
}
- 카테고리 엔티티
@Entity
public class Category {
@Id @GeneratedValue
@Column(name = "CATEGORY_ID")
private Long id;
private String name;
@ManyToMany
@JoinTable(name = "CATEGORY_ITEM",
joinColumns = @JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = @JoinColumn(name = "ITEM_ID"))
private List<Item> items = new ArrayList<Item>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARENT_ID")
private Category parent;
@OneToMany(mappedBy = "parent")
private List<Category> child = new ArrayList<Category>();
//==연관관계 메서드==//
public void addChildCategory(Category child) {
this.child.add(child);
child.setParent(this);
}
// Getter, Setter
...
}
- 주소 값 타입
@Embeddable
public class Address {
private String city;
private String street;
private String zipcode;
// Getter, Setter
...
}
'Java-Spring > 자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 스프링 데이터 JPA ① (0) | 2022.05.16 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 웹 애플리케이션 제작 ③ - 애플리케이션 구현 (0) | 2022.05.15 |
[자바 ORM 표준 JPA 프로그래밍] 웹 애플리케이션 제작 ① - 프로젝트 환경설정 (0) | 2022.05.12 |
[자바 ORM 표준 JPA 프로그래밍] 객체지향 쿼리 언어 ⑥ - 심화 (0) | 2022.05.07 |
[자바 ORM 표준 JPA 프로그래밍] 객체지향 쿼리 언어 ⑤ - 네이티브 SQL (0) | 2022.05.06 |