프로그래밍/spring boot

[스프링부트] 실전! 스프링 부트와 JPA 활용1 #2-3 엔티티 클래스 개발1

aSpring 2023. 10. 27. 20:23
728x90
728x90
※ 본 포스팅은 김영한 강사님의 인프런 '실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발' 강의를 들으며 작성한 수강일지 입니다.

 

| 도메인 분석 설계

1. 요구사항 분석
2. 도메인 모델과 테이블 설계
3. 엔티티 클래스 개발1
4. 엔티티 클래스 개발2
5. 엔티티 설계시 주의점

 

3. 엔티티 클래스 개발 1

- 실무에서는 가급적 Getter는 열어두고, Setter는 꼭 필요한 경우에만 사용하기

 

class, enum

package jpabook.jpashop.domain;

import lombok.Getter;
import lombok.Setter;

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

@Entity
@Getter @Setter // lombok으로 getter, setter 열어두기
public class Member {

    @Id @GeneratedValue
    @Column(name = "member_id") // column명s
    private Long id;

    private String name;

    @Embedded // 내장 type을 포함했다는 annotation으로 mapping
    private Address address;

    @OneToMany(mappedBy = "member") // order 테이블의 member filed에 의해 매핑된 것(매핑된 거울 -> 읽기 전용), 여기에 값을 적는다고해서 FK가 변경되지 않음
    private List<Order> orders = new ArrayList<>();
}
package jpabook.jpashop.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") // 관례상 예약어 order로 table명이 생성되지 않게 orders로 적어줌
@Getter
@Setter
public class Order {

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

    // member와 관계 세팅 -> 양방향 -> 연관관계의 주인을 정해주어야 함(값이 바뀌면 뭘 보고 해야하나? FK가 있는 쪽을 연관관계의 주인으로 설정)
    @ManyToOne
    @JoinColumn(name = "member_id") // mapping을 뭘로 할 것이냐 => member_id가 FK가 됨
    private Member member;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();

    @OneToOne
    @JoinColumn(name = "delivery_id")
    private Delivery delivery;

    // private Date data; // date 관련된 annotation 줘야했는데 java 8에서는 아래 사용하면 됨
    private LocalDateTime orderDate;

    private OrderStatus status; // 주문 상태 [ORDER, CANCEL]
}
package jpabook.jpashop.domain;

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

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; //주문 수량
}
package jpabook.jpashop.domain;

import lombok.Getter;

import javax.persistence.Embeddable;

@Embeddable // 어딘가에 embed해서 쓰일 수 있다
@Getter
public class Address {

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

    // JPA 스펙상.. 생성자 필요(public으로하면 누구나 호출 가능하므로 protected까진 허용)
    protected Address() {
    }

    public Address(String city, String street, String zipcode) {
        this.city = city;
        this.street = street;
        this.zipcode = zipcode;
    }
}
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
}
package jpabook.jpashop.domain;

public enum DeliveryStatus {
    READY, COMP
}
package jpabook.jpashop.domain;

public enum OrderStatus {
    ORDER, CANCEL
}

 

- 연관관계의 주인 설정

Member와 Order의 관계를 바꾸고 싶으면 FK 값을 변경해야 하는데,

Member 쪽에도 orders 필드가 있고 반대로 Order 쪽에도 member 필드가 있다.

JPA에서는 어디의 값이 변경되었을 때 FK 키를 바꾸어야 하는가?

FK 값을 어디서 update를 쳐야하는가?

 

얘의 값이 변경되었을 때, 저 FK를 바꿀거야! -> 이게 연관관계의 주인

FK와 가까운 아이로 정하라.

 

여기서는 FK가 있는 Order를 연관관계의 주인으로 설정

-> 주인이 아닌 아이는 추가로 어떤 필드에 의해 매핑된 것인지(누구의 거울인지) 적어주기

@OneToMany(mappedBy = "member") // order 테이블의 member filed에 의해 매핑된 것
    private List<Order> orders = new ArrayList<>();

 

※ Member에 코드를 적을 때, 없는 Class를 적고 Alt + Enter -> Create class

 

- EnumType -> Enumerated를 꼭 써주고, type은 STIRNG, ORDINAL이 있는데 ORDINAL은 숫자로 들어가므로 중간에 type이 더 생기는 등의 경우 순서가 밀리면서 문제 생길 수 있음

 

- 1:1 관계에서는 FK를 어디에 두어도 상관없으며 어디에 두느냐에 따라 각각 장단점이 있는데 강사님 선호 -> access를 많이 하는 쪽

ex) Orders, Delivery --> Orders를 더 많이 찾기 때문에 Orders에 FK 두고, 따라서 연관관계의 주인도 Orders가 됨

 

item package

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

    // 상속 관계 mapping

    // 아래 것들은 item들의 공통 속성
    private String name;
    private int price;
    private int stockQuantity;
}
728x90
728x90