스프링 부트와 JPA 활용1 - 도메인 분석 설계 2

JOY·2022년 3월 14일
0
post-thumbnail

📌 스프링 부트와 JPA 활용1 - 도메인 분석 설계 2

인프런 - 스프링 부트와 JPA 활용1 by 김영한 을 기반으로 작성된 글입니다.
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발


도메인 분석 설계 목차

1. 요구사항 분석

2. 도메인 모델과 테이블 설계

3. 엔티티 클래스 개발1

4. 엔티티 클래스 개발2

5. 엔티티 설계시 주의점


도메인 분석 설계

3. 엔티티 클래스 개발1

1) 회원 엔티티 (Member.java)

💻 코드

package jpabook.jpashop.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
    private Address address;

    @OneToMany(mappedBy = "member")
    private List<Order> orders = new ArrayList<>();
}

👉 설명
엔티티 식별자 : id
pk 컬럼명 : member_id

  • 하나의 회원이 여러개 의 상품을 주문 : 일대다관계
    연관관계의 주인이 아닐 경우 mappedBy 사용
    orders 테이블에 있는 member 필드에 의해 연관관계 매핑
    여기서 값을 설정해도 fk 값이 변경되지 않음

2) 주문 엔티티 (Order.java)

💻 코드

package jpabook.jpashop.domain;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.time.LocalDate;
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;

    /*Orders 와 Member는 다대일관계. Orders가 연관관계 주인 */
    /*fk 이름 : member_id*/
    @ManyToOne
    @JoinColumn(name="member_id")
    private Member member;

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

    @OneToOne
    @JoinColumn(name="delivery_id")
    /*설명*/
    private Delivery delivery;

    //Java 8 에서는 LocalDateTime 사용 시
    //hibernate가 자동으로 지원
    private LocalDateTime orderDate; //주문시간

    @Enumerated(EnumType.STRING)
    private OrderStatus status; //주문상태 [Order, Cancel]
}

👉 설명

@ManyToOne @OneToMany
외래키가 있는 부분을 연관관계 주인으로 정하기

  • 각자 연관관계가 있는 field를 가지고 있기 때문에
    Member와 order의 관계를 바꾸고 싶다면, FK의 값을 변경해야함
    그러나! 각자 연관관계가 있는 field를 가지고 있기 때문에
    어느 값을 변경해야할지 JPA가 혼란스러울 수 있음
    ❗ FK값을 update 할 테이블을 연관관계의 주인으로 설정

@OneToOne
일대일관계에서는 연관관계 주인을 접근 많이 하는 테이블에 두면 좋음

3) 주문상품 엔티티 (OrderItem.java)

💻 코드

package jpabook.jpashop.domain;

import jpabook.jpashop.domain.item.Item;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Getter @Setter
@Table
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;  //주문 수량
}

4) 주문 상태 (OrderStatus.java)

💻 코드

package jpabook.jpashop.domain;

public class OrderStatus {
    //ORDER, CANCEL
}

5) 상품 엔티티 (Item.java)

💻 코드

package jpabook.jpashop.domain.item;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@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;
}

👉 설명
@Inheritance : 상속관계 매핑
strategy : 전략 지정 값 - SINGLE_TABLE, TABLE_PER_CLASS, JOINED

6) 상품 - 도서 엔티티 (Book.java)

💻 코드

package jpabook.jpashop.domain.item;

import lombok.Getter;
import lombok.Setter;

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

@Entity
@DiscriminatorValue("B")
@Getter @Setter
public class Book extends Item{

    private String author;
    private String isbn;
}

7) 상품 - 음반 엔티티 (Album.java)

💻 코드

package jpabook.jpashop.domain.item;

import lombok.Getter;
import lombok.Setter;

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

@Entity
@DiscriminatorValue("A")
@Getter @Setter
public class Album extends Item {

    private String artist;
    private String etc;
}

8) 상품 - 영화 엔티티 (Movie.java)

💻 코드

package jpabook.jpashop.domain.item;

import lombok.Getter;
import lombok.Setter;

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

@Entity
@DiscriminatorValue("M")
@Getter @Setter
public class Movie extends Item{

    private String director;
    private String actor;
}

9) 배송 엔티티 (Delivery.java)

💻 코드

package jpabook.jpashop.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; //READY(배송 준비), COMP(배송)

}

👉 설명

  • EnumType 값 - ORDINAL, STRING

    EnumType 의 default 값은 ORDINAL
    ORDINAL 은 컬럼 값을 순차적 숫자로 매겨줌
    그러나 중간에 새로운 값 추가가 되면 순서가 밀려 문제가 됨
    이럴때는 꼭 STRING 값 사용

    ❗ ex ) READY, COMP 순서대로 1, 2
    갑자기 중간에 XXX 값이 들어와버리면 READY, XXX, COMP 로 변경돼 순서가 밀려버린다

10) 배송 상태 (DeliveryStatus.java)

💻 코드

package jpabook.jpashop.domain;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.Entity;

public enum DeliveryStatus {
//READY(배송 준비), COMP(배송)
}

11) 주소 엔티티 (Address.java)

💻 코드

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;
}

👉 설명
@Embeddable : JPA의 내장타입

profile
Just Do IT ------- 🏃‍♀️

0개의 댓글