[Spring Boot2][2] 2. ドメイン解析設計
44505 ワード
🏷 需要分析
1𗞚𗞚会員機能
🏷 ドメインモデルとテーブルの設計
勘定科目の勘定科目ドメインモデルと表設計
1𗞚会員、注文、商品の関係
✔¥会員実体分析
1”メンバー(メンバー)
注文状態は列挙型を採用し、注文、キャンセルを表すことができる.
✔¥会員表分析
1️⃣ MEMBER
勘定科目の関連付けのマッピング分析
1」会員と注文
(表中**無条件に「マルチ」に外部キーが存在します!)
Order.member
・ORDERS.MEMBER_ID
外来鍵とマッピングする.OrderItem.order
・ORDER_ITEM.ORDER_ID
外来鍵とマッピングする.OrderItem.item
乙ORDER_ITEM.ITEM_ID
外来鍵とマッピングする.=一対一の双方向関係.
Order.delivery
とORDERS.DELIVERY_ID
外来鍵をマッピングします.@ManyToMany
を使用してマッピングを行います.(実務では使用しない
@ManyToMany
、ここでは多対多関係を例に追加しただけです!)🏷 エンティティークラスの開発
📌 リファレンス
Getter
Setter
、できるだけ設計を簡略化Getter
、Setter
必要なときのみ使用!✔メンバーエンティティ
package jpabook.jpashop.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
@Column(name = "member_id")
private Long id;
private String name;
@Embedded
private Address address;
@JsonIgnore
@OneToMany(mappedBy = "member")
private List<Order> orders = new ArrayList<>();
}
✔Order-受注エンティティ
package jpabook.jpashop.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.BatchSize;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import static javax.persistence.FetchType.*;
@Entity
@Table(name = "orders")
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {
@Id @GeneratedValue
@Column(name = "order_id")
private Long id;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "member_id")
private Member member;
@JsonIgnore
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
private List<OrderItem> orderItems = new ArrayList<>();
@JsonIgnore
@OneToOne(fetch = LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "delivery_id")
private Delivery delivery;
private LocalDateTime orderDate; //주문시간
// Enum 타입은 @Enumerated(EnumType.STRING) 꼭 필요! -> 문자열로 출력
@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);
}
}
✔orderItem-受注商品エンティティ
package jpabook.jpashop.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jpabook.jpashop.domain.item.Item;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import static javax.persistence.FetchType.*;
@Entity
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class OrderItem {
@Id @GeneratedValue
@Column(name = "order_item_id")
private Long id;
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "item_id")
private Item item;
@JsonIgnore
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "order_id")
private Order order;
private int orderPrice; //주문 가격
private int count; //주문 수량
//==생성 메서드==//
public static OrderItem createOrderItem(Item item, int orderPrice, int count) {
OrderItem orderItem = new OrderItem();
orderItem.setItem(item);
orderItem.setOrderPrice(orderPrice);
orderItem.setCount(count);
item.removeStock(count);
return orderItem;
}
}
✔¥Item-商品図元
package jpabook.jpashop.domain.item;
import jpabook.jpashop.domain.Category;
import jpabook.jpashop.exception.NotEnoughStockException;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.BatchSize;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
// 싱글 테이블 전략
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
// 구별할 타입을 정해줌
@DiscriminatorColumn(name = "dtype")
@Getter @Setter
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<>();
}
✔Delivery-出荷元
package jpabook.jpashop.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import static javax.persistence.FetchType.*;
@Entity
@Getter @Setter
public class Delivery {
@Id @GeneratedValue
@Column(name = "delivery_id")
private Long id;
@JsonIgnore
@OneToOne(mappedBy = "delivery", fetch = LAZY)
private Order order;
@Embedded
private Address address;
// Enum 타입은 @Enumerated(EnumType.STRING) 꼭 필요! -> 문자열로 출력
@Enumerated(EnumType.STRING)
private DeliveryStatus status; //READY, COMP
}
✔範疇図元
package jpabook.jpashop.domain;
import jpabook.jpashop.domain.item.Item;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
import static javax.persistence.FetchType.*;
@Entity
@Getter @Setter
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<>();
// 내 부모 - 부모는 하나임
@ManyToOne(fetch = LAZY)
@JoinColumn(name = "parent_id")
private Category parent;
// 내 자식 - 자식은 여러명을 가질 수 있음
@OneToMany(mappedBy = "parent")
private List<Category> child = new ArrayList<>();
//==연관관계 메서드==//
public void addChildCategory(Category child) {
this.child.add(child);
child.setParent(this);
}
}
📌 仕事中は使わない@ManyToMany
@ManyToMany
便利そうですが、中間表(CATEGORY_ITEM
)にコラムを追加することができず、細かい照会が難しいため、実際の作業での使用は限られています.CategoryItem
・@ManyToOne
後に使用!✔@OneToMany-アドレス値タイプ
package jpabook.jpashop.domain;
import lombok.Getter;
import javax.persistence.Embeddable;
// JPA의 내장타입 : 어디든 내장될 수 있다는 뜻
@Embeddable
@Getter
public class Address {
private String city;
private String street;
private String zipcode;
protected Address() {
}
public Address(String city, String street, String zipcode) {
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
}
📌 値のタイプは変更できないように設計します.除去
Address
ジェネレータですべての値を初期化し、変更不可のクラスを作成!@Setter
)java基本生成者を@Embeddable
またはdefault constructor
public
よりprotected
の方が安全!🏷 設計上の注意事項
1πはなるべくセルに対してSetterを使用しない
・𐂍𐂍・𐂊𐂊」」」」」」」
public
除く!2▼▼▼すべての関連関係を遅延ロードに設定
protected
)予測が難しく、どのSQLが実行されるかを追跡することも難しい.特にJPQLを実行するとN+1の問題がしばしば発生する.
Setter
関係は基本的にインスタントロードであり、ダイレクトディレイロードに設定すべき!3▼▼▼▼▼▼▼▼▼▼▼▼▼\96
private List<Order> orders = new ArrayList<>();
Reference
この問題について([Spring Boot2][2] 2. ドメイン解析設計), 我々は、より多くの情報をここで見つけました https://velog.io/@sorzzzzy/Spring-Boot22-2.-도메인-분석-설계テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol