프로그래밍/spring boot

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

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

 

| 도메인 분석 설계

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

 

4. 엔티티 클래스 개발 2

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;

@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 = "cetegory_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<>();
}
- 다대다 관계 -> 중간 테이블 category_item 생성
FK category_id, FK item_id 두 column만 들어가게 되는데 사실 다른 것들을 더 넣기 어려움 -> 실무에서는 저렇게 단순하게 매핑하게 되는 경우가 없음 -> 개인적으로 하는 프로젝트면 모를까 실무에서는 ManyToMany 사용하지 말것

 

package jpabook.jpashop.domain.item;

import jpabook.jpashop.domain.Category;
import lombok.Getter;
import lombok.Setter;

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;

    // 상속 관계 mapping

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

    @ManyToMany(mappedBy = "items")
    private List<Category> categories = new ArrayList<>();
}

 

실행

1) db 실행

2) 원하는대로 테이블이 생성되었는지 확인

- refresh해서 생성된 테이블 확인

- column들도 확인

 

- JPA는 이렇게 alter .. 해서 FK table 다 잡아줌

 

이론적으로는 Getter, Setter 모두 제공하지 않고 꼭 필요한 별도의 메서드를 제공하는게 가장 이상적이나
실무에서는 조회할 일이 정말 많기 때문에 기본적으로 Getter는 열어두는 것이 편함(값이 변하지 않음)
그러나 Setter를 호출하면 데이터가 변하기 때문에 가까운 미래에 이 Entity가 언제, 어디서 바뀌는지 알 수가 없음
변경할 때는 Setter 대신에 변경 지점이 명확하도록 변경을 위한 비즈니스 메서드를 별도로 제공하는 것이 좋음
-> 그래야 유지보수가 용이함

 

값 타입

값이라는 것 자체는 변경 불가능하게 설계해야 함
@Setter를 제거하고 생성자에서 값을 모두 초기화해서 변경 불가능한 클래스로 만들기
JPA 스펙상 엔티티나 임베디드 타입(@Embeddable)은 자바 기본 생성자(default constructor)를 public 또는 protected로 설정해야 함(public으로 두는 것보다는 protected로 설정하는 것이 그나마 더 안전함)

JPA가 이런 제약을 두는 이유?
- JPA 구현 라이브러리가 객체를 생성할 때 리플랙션 같은 기술을 사용할 수 있도록 지원해야 하기 때문

 

반복적으로 생성 해보면서 내가 원하는대로 생성이 되는지, 수정하고 정리하기

 

 

다음시간

엔티티 설계시 주의점

728x90
728x90