[DMD] 2. 엔티티 설계

sorzzzzy·2021년 10월 28일
0

Spring Project

목록 보기
2/18
post-thumbnail

프로젝트 기본 틀을 잡았으니 엔티티부터 설계해보도록 하겠다☺️
일단 기본적으로 연관관계 매핑까지만 고려했음

즐거운 마음으로 시~작 ^_^


✔️ Member - 회원 엔티티

package sorzzzzy.dearmydog.domain;

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
    @Enumerated(EnumType.STRING) // 임베디드 타입은 '@Enumerated' 이 꼭 필요함
    private Address address;

    // 연관관계의 주인이 아닌 쪽에는 'mappedBy' 사용
    // 여기서 member는 'Order 테이블에 있는 member 필드에 의해 mapped 됐다' 는 의미
    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();

}
  • 임베디드 타입은 @Enumerated을 꼭 사용하기

✔️ Order - 주문 엔티티

package sorzzzzy.dearmydog.domain;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "orders")
@Getter @Setter
public class Order {

    @Id @GeneratedValue
    @Column(name = "order_id")
    private Long id;

    @ManyToOne
    @JoinColumn(name = "member_id") // foreign key 는 '다'인 order 가 가짐
    private Member member;

    @OneToMany(mappedBy = "order")
    private List<OrderItem> orderItems = new ArrayList<>();

    @OneToOne
    @JoinColumn(name = "delivery_id") // 일대일인 경우, FK는 아무곳에나 있어도 되는데 여기서는 접근을 더 많이 하는 order 에 둠
    private Delivery delivery;

    private LocalDateTime orderDate;

    private OrderStatus status;
}

foriegn key를 가지는 엔티티가 어떤 엔티티인지 잘 고려해보자!

  • 일대다, 다대일인 경우는 에 초점을 맞춤
  • 일대일인 경우, 어떤 곳이든 상관은 없지만 접근을 더 많이 하는 곳 기준에서 생각하면 좋다. 여기서는 Order 에 맞춤

✔️ OrderItem - 주문상품 엔티티

package sorzzzzy.dearmydog.domain;

import lombok.Getter;
import lombok.Setter;
import sorzzzzy.dearmydog.domain.Item.Item;

import javax.persistence.*;

@Entity
@Getter @Setter
public class OrderItem {

    @Id @GeneratedValue
    @Column(name = "order_item_id")
    private Long id;

    @ManyToOne
    @JoinColumn(name = "item_id")
    private Item item;

    @ManyToOne
    @JoinColumn(name = "order_id")
    private Order order;

    private int orderPrice;

    private int count;
}

✔️ Delivery - 배송 엔티티

package sorzzzzy.dearmydog.domain;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Getter @Setter
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;
}
  • 값타입을 가지는 쪽은 @Embedded 필요
  • Enum 타입을 가지는 DeliveryStatus@Enumerated(EnumType.STRING) 필요

✔️ Address - 주소(값타입)

package sorzzzzy.dearmydog.domain;

import lombok.Getter;

import javax.persistence.Embeddable;

@Embeddable
@Getter
public class Address {

    private String city;
    private String street;
    private String zipcode;

    // JPA 스펙 상 엔티티나 임베디드 타입은 기본 생성자를 protected 또는 public 으로 설정해야 함
    protected Address() {

    }

    // 값 타입은 변경 불가능하게 설계해야 함
    // setter를 제거하고 생성자에서 값을 모두 초기화해 변경 불가능한 클래스를 만듦
    public Address(String city, String street, String zipcode) {
        this.city = city;
        this.street = street;
        this.zipcode = zipcode;
    }
}
  • JPA 스펙 상 엔티티나 임베디드 타입은 기본 생성자를 protected 또는 public 으로 설정해야 함
  • 값 타입은 변경 불가능하게 설계해야 함
  • setter를 제거하고 생성자에서 값을 모두 초기화해 변경 불가능한 클래스를 만듦

✔️ Item - 상품 엔티티

package sorzzzzy.dearmydog.domain.Item;

import lombok.Getter;
import lombok.Setter;
import sorzzzzy.dearmydog.domain.Category;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
// 상속관계 지정 - 싱글테이블 전략
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
// dtype 으로 분류
@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<>();
}
  • @Inheritance(strategy = InheritanceType.SINGLE_TABLE)상속관계 지정

🏷 Toy

package sorzzzzy.dearmydog.domain.Item;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@Getter
@Setter
@DiscriminatorValue("T")
public class Toy extends Item{

    private String component;
    private String size;
}

🏷 Food

package sorzzzzy.dearmydog.domain.Item;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@Getter
@Setter
@DiscriminatorValue("F")
public class Food extends Item {

    private String allowance;
    private String ingredient;
}

🏷 Clothes

package sorzzzzy.dearmydog.domain.Item;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@Getter
@Setter
@DiscriminatorValue("C")
public class Clothes extends Item {

    private String season;
    private String color;
}

✔️ Category - 카테고리 엔티티

package sorzzzzy.dearmydog.domain;

import lombok.Getter;
import lombok.Setter;
import sorzzzzy.dearmydog.domain.Item.Item;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@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
    @JoinColumn(name = "parent_id")
    private Category parent;

    @OneToMany(mappedBy = "parent")
    private List<Category> child = new ArrayList<>();
}

카테고리 엔티티는 상품과 다대다 관계인데 이것을 일대다, 다대일로 풀어내기 위해서는 중간테이블이 필요하다!

  • @JoinTable로 각각을 중간테이블에 매핑함
   @ManyToOne
    @JoinColumn(name = "parent_id")
    private Category parent;

    @OneToMany(mappedBy = "parent")
    private List<Category> child = new ArrayList<>();

이처럼 한 엔티티 안에서 간편하게 상속관계를 지정할 수 있다.


✔️ 실행

➡️쿼리가 아주 깔끔하죠? 굳^^➡️ h2 데이터베이스에도 잘 반영된 것을 확인


다음 시간부터는 이제 연관관계를 지연로딩으로 바꾸고 도메인을 차례로 개발해보겠다!

profile
Backend Developer

0개의 댓글