다양한 연관관계 매핑
- 요구사항 추가
- 상품을 주문할 때 배송 정보를 입력할 수 있으므로 주문과 배송은 일대일 관계
- 상품을 카테고리로 구분할 수 있음
- ERD 분석
- 주문과 배송 : 주문과 배송은 일대일 관계, 외래 키는 주문 테이블에 존재
- 상품과 카테고리 : 한 상품은 여러 카테고리에 속할 수 있고, 한 카테고리도 여러 상품을 가지므로 다대다 관계이지만,
다대다 관계를 표현하기 어려우므로 CATEGORY_ITEM 연결 테이블을 추가해서 일대다, 다대다 관계로 풀어냄
일대일 매핑
- 주문과 배송의 관계
Order와 Delivery는 일대일 관계
@Entity
@Table(name = "ORDERS")
public class Order { // 주문 엔티티
@Id @GeneratedValue
@Column(name = "ORDER_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "MEMBER_ID")
private Member member; // 주문 회원
@OneToMany(mappedBy = "order")
private List<OrderItem> orderItems = new ArrayList<OrderItem>();
@OneToOne // Order와 Delivery는 일대일 관계, 연관관계의 주인
@JoinColumn(name = "DELIVERY_ID")
private Delivery delivery; // 배송정보
private Date orderDate; // 주문시간
@Enumerated(EnumType.STRING)
private OrderStatus status; // 주문상태
// ==연관관계 메서드== //
public void setMember(Member member) {
// 기존 관계 제거
if (this.member != null) {
this.member.getOrders().remove(this);
}
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
public class Delivery { // 배송 엔티티
@Id @GeneratedValue
@Column(name = "DELIVERY_ID")
private Long id;
@OneToOne(mappedBy = "delivery") // Order와 Delivery는 일대일 관계, 연관관계의 주인이 아님
private Order order;
private String city;
private String street;
private String zipcode;
@Enumerated(EnumType.STRING)
private DeliveryStatus status; // ENUM [READY(준비), COMP(배송)]
// Getter, Setter
...
}
public enum DeliveryStatus { // 배송상태 엔티티
READY, // 준비
COMP // 배송
}
다대다 매핑
- 카테고리와 상품
Category와 Item은 다대다 관계이므로, CATEGORY_ITEM 연결 테이블을 추가
@Entity
public class Category { // 카테고리 엔티티
@Id @GeneratedValue
@Column(name = "CATEGORY_ID")
private Long id;
private String name;
@ManyToMany // Category와 Item은 다대다 관계, 연관관계의 주인
// @ManyToMany와 @JoinTable을 사용해 CATEGORY_ITEM 연결 테이블을 바로 매핑
/* 다대다 관계는 연결 테이블을 JPA가 알아서 처리해주므로 편리하지만
연결 테이블에 필드가 추가되면 더는 사용할 수 없으므로
CategoryItem이라는 연결 엔티티를 만들어서 일대다, 다대일 관계로 매핑하는 것을 권장 */
@JoinTable(name = "CATEGORY_ITEM",
joinColumns = @JoinColumn(name = "CATEGORY_ID"),
inverseJoinColumns = @JoinColumn(name = "ITEM_ID"))
private List<Item> items = new ArrayList<Item>();
// 카테고리의 계층 구조를 위한 필드들
@ManyToOne
@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);
}
public void addItem(Item item) {
items.add(item);
}
// Getter, Setter
...
}
@Entity
public class Item { // 상품 엔티티
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private Long id;
private String name; // 이름
private int price; // 가격
private int stockQuantity; // 재고수량
@ManyToMany(mappedBy = "items") // Category와 Item은 다대다 관계, 연관관계의 주인이 아님
private List<Category> categories = new ArrayList<Category>();
// Getter, Setter
...
}
- 다대다 관계는 연결 테이블을 JPA가 알아서 처리해주므로 편리하지만 연결 테이블에 필드가 추가되면 더는 사용할 수 없으므로
CategoryItem이라는 연결 엔티티를 만들어서 일대다, 다대일 관계로 매핑하는 것을 권장