본문 바로가기
Spring/스프링 JPA 활용

[스프링 JPA 1편] 2 - (1) 도메인 분석 설계

by Poorm 푸름 2023. 12. 12.

 *  Mac사용, Java17 사용

 *  진도 : 섹션2-(1) ~ (4) 
 *          : 자바 클래스명,         : 코드,         : 단축키

 

1. 요구사항 분석

  • 회원
    • 회원 등록
    • 회원 조회 상품 기능
  • 상품 
    • 상품 등록
    • 상품 수정
    • 상품 조회
  • 주문
    • 상품 주문
    • 주문 내역 조회
    • 주문 취소
  • 기타
    • 상품은 재고 관리 필요
    • 상품의 종류 : 도서, 음반, 영화
    • 상품을 카테고리로 구분 가능
    • 상품 주문시 배송 정보 입력

 

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

 

1) 테이블

- 회원 / 주문 / 배송 / 주문 상품 / 카테고리 / 상품 / 배송 / 도서, 음반, 영화

 

< 회원 - 주문 >

  • 회원은 여러 상품을 주문할 수 있다 = 1:N

< 주문 - 배송 >

  • 주문할 때 배송정보 필요 = 1:1

< 주문 - 주문한 상품 - 상품 >

  • 한 번 주문할 때 여러 상품을 주문할 수 있고 하나의 상품이 여러 주문에 담길 수 있다 = N:N
  • < 주문 - 주문한 상품 > = 1:N /  < 주문한 상품 - 상품 > = N : 1
  • 다대다 관계는 좋지 않아서 1:N 혹은 N:1 관계로 변경하는게 좋다 → 주문상품 엔티티 추가

< 상품 - 카테고리에 있는 상품 - 카테고리 >

  • 하나의 상픔이 여러 카테고리에 들어갈 수 있고 하나의 카테고리에 여러 상품이 들어갈 수 있다 = N:N
  • 다대다 관계는 좋지 않아서 1:N 혹은 N:1 관계로 변경하는게 좋다 → 카테고리에 있는 상품 엔티티 추가

< 상품의 종류_도서, 음반, 영화 >

  • 상품이라는 공통 속성을 사용하므로 상속 구조로 표현 

 

2) ERD 및 연관관계 매핑 분석

 

 

< member > < orders > < order_item > < item >
  • member_id(PK)
  • name 이름
  • address 주소
    (임베디드 타입)
  • order_id(PK)
  • member_id(FK) 
    (어떤 회원이 주문했는지 확인)
  • delivery_id(FK) 배송 정보
  • oderdate 주문 날짜
  • status 주문 상태
  • order_item_id(PK)
  • order_id(FK) 주문 정보
  • item_id(FK) 상품 정보
  • orderPrice 주문 금액
  • count 주문 수량
  • item_id(PK)
  • name 이름
  • price 가격
  • stockquantity 재고 수량
  • Dtype 상품 종류
    (도서, 음반, 영화)
< category > < category_item > < delivery > < address >
  • category_id(PK)
  • parent_id(FK)
  • name 이름
  • category_id(FK) 카테고리 정보
  • item_id(FK) 상품 정보
  • delivery_id (FK)
  • status 배송 상태
  • address 주소
    (
    임베디드 타입)
  • city (FK)
  • street 배송 상태
  • zipcode   
    (임베디드 타입)

  

  • 1:N에서의 FK는 무조건 N에 있다
  • 1:N, N:N의 양방향 관계는 주인을 정해야한다 (외래키가 있는 테이블을 연관 관계 주인으로 정하는 것이 좋다)
  • 연관관계 주인에서 셋팅해야 값이 변경된다

 

< member - orders >

1:N (양방항)

주문 테이블 → 외래키 갖고 있다  주인
= ORDERS.member_id 외래 키와 매핑


orders - order_item >

1:N (양방향) 

주문_상품 테이블  외래 키 갖고 있다  연관관계의 주인
ORDER_ITEM.order_id 외래 키와 매핑


 

< order_item - item >

N:1 

나를 주문한 odrder_item 모두 찾아! 이런 경우는 없으니 단방향

= ORDER_ITEM.item_id 외래 키와 매핑
< orders - delivery > 

1:1 (양방항)

주문 테이블  외래키 갖고 있다  주인

= ORDERS.delivery_id 외래 키와 매핑
 

< item - category_item >

1:N

카테고리_상품 테이블  외래키 갖고 있다  주인

= CATEGORY_ITEM.item_id 외래 키와 매핑
 

< category_item - category >

N:1

카테고리_상품 테이블  외래키 갖고 있다  주인

=CATEGORY_ITEM.category_id 외래 키와 매핑

 

 

3. 엔티티 클래스 개발


1) Member
[ src - java - jpabook.jpashop - domain -  Member ]

 

- 엔티티, 롬복 사용 @Entity @Getter @Setter

- 기본키 생성 및 전략 @Id @GeneratedValue

 

- 테이블의 컬럼과 연결될 대상에 '표시' @Column(name = "member_id")

  • 테이블(클래스)의 ID와 외래키 컬럼의 이름을 동일하게 맞춰주기 위해
  •  필드 생성 private ~
    • id, name

- JPA 내장 타입 (사용하는 곳에 표시) @Embedded → Address

  • 위처럼 쓰든지 address 클래스가서 @Embeddable 쓰든지 둘 중 하나만 써도 괜춘
  • 필드 생성 private ~
    • Address address
       

- 1:N 관계 (member 입장에서)' @OneToMany(mappedBy = "member")

  • 하나의 회원이 여러개의 상품 주문 = 1:N
  • member 연관관계 주인X / order에서 가져다 씀 = mappedBy사용
  •  필드 생성 private ~
    • orders(list)

2) Address [ src - java - jpabook.jpashop - domain -  Address ]

- JPA 내장 타입 (정의하는 곳에 표시) @Embeddable

  • 필드 생성 private ~
    • city, street, zipcode

  • 기본 생성자 protected ~ (command + N)
    • 값 타입은 변경 불가능하게 설계해야 하므로 @Setter 지우고 기본생성자로 초기화한다

      public을 protected로 수정하는 것이 더 안전

  • 전체 생성자 public ~ (command + N)_모두 선택

3) Order [ src - java - jpabook.jpashop - domain -  Order ]

 

- 엔티티, 롬복 사용 @Entity @Getter @Setter

- 엔티티와 매핑할 테이블을 지정 @Table(name"orders")

- 기본키 생성 및 전략 @Id @GeneratedValue

 

테이블의 컬럼과 연결될 대상에 '표시' @Column(name = "order_id")

  • 테이블(클래스)의 ID와 외래키 컬럼의 이름을 동일하게 맞춰주기 위해
  •  필드 생성 private ~
    • id , orderDate

- N : 1 관계 (order 입장에서)'@ManyToOne 

FK @JoinColumn(name = "member_id")

  • order가 연관관계 주인
  • 필드 생성 private ~
    • Member member

 

- 1 : N 관계 (order 입장에서) @OneToMany(mappedBy = "order")

  • order 연관관계 주인X / orderItem에서 가져다 씀 = mappedBy사용
  • 필드 생성 private ~
    • orderitems(list)

 

- 1 : 1 관계 @OneToOne

FK @JoinColumn(name = "delivery_id")

  • 1:1 관계는 FK 어디에 둬도 상관없지만 주로 엑세스 많이 하는 곳에 두기
  • 필드 생성 private ~
    • Delivery delivery

 

- enum 타입을 매핑 @Enumerated(EnumType.STRING) 

  • EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
    EnumType.STRING : enum 이름을 데이터베이스에 저장
  • 필드 생성 private ~
    • Orderstatus orderstatus

- 연관관계 메서드

 

4) OrderItem [ src - java - jpabook.jpashop - domain -  OrderItem ]

- 엔티티, 롬복 사용 @Entity @Getter @Setter

- 엔티티와 매핑할 테이블을 지정 @Table(name"order_item")

 

- 기본키 생성 및 전략 @Id @GeneratedValue

 

테이블의 컬럼과 연결될 대상에 '표시' @Column(name = "order_item_id")

  • 테이블(클래스)의 ID와 외래키 컬럼의 이름을 동일하게 맞춰주기 위해
  •  필드 생성 private ~
    • id 

- N : 1 관계 (OrderItem 입장에서)'@ManyToOne 

FK @JoinColumn(name = "item_id")

  • order가 연관관계 주인
  • 필드 생성 private ~
    • Item item

- N : 1 관계 (OrderItem 입장에서)'@ManyToOne 

FK @JoinColumn(name = "order_id")

  • order가 연관관계 주인
  • 필드 생성 private ~
    • Order order, orderPrice, count 

5) enum

 

OrderStatus [ src - java - jpabook.jpashop - domain -  OrderStatus ]

ORDER, CANCEL

 

 

DeliveryStatus [ src - java - jpabook.jpashop - domain -  DeliveryStatus ]

READY, COMP

 

6) Item [ src - java - jpabook.jpashop - domain -  Item ]

 

- 엔티티, 롬복 사용 @Entity @Getter @Setter

 

-  부모클래스에 상속 매핑 @Inheritance(~SINGLE_TABLE)

더보기

싱글테이블 전략 InheritanceType.SINGLE_TABLE

 

장점 - 조인 필요 없어서 조회 성능이 빠르고 조회 쿼리가 단순

단점 - 매핑한 컬럼은 모두 null 허용, 단일 테이블에 모든 것을 저장하므로 테이블이 커져 오히려 성능 느려질 수도 있다

주의 - 구분 컬럼을 꼭 사용하기 ( @DiscriminatorColumn )

 

-  부모클래스에 구분칼럼 지정 @DiscriminatorColumn(name="dtype")

 

- 추상관계 public abstract ~

 

- 기본키 생성 및 전략 @Id @GeneratedValue

 

테이블의 컬럼과 연결될 대상에 '표시' @Column(name = "tem_id")

  • 테이블(클래스)의 ID와 외래키 컬럼의 이름을 동일하게 맞춰주기 위해
  •  필드 생성 private ~
    • id, name, price, stockQuantity

N : N 관계 @ManyToMany(mappedBy = "items")

  • 테이블(클래스)의 ID와 외래키 컬럼의 이름을 동일하게 맞춰주기 위해
  •  필드 생성 private ~
    • category(list)

7) Item 상속 디렉토리

 

Album [ src - java - jpabook.jpashop - domain - item - Album ]

 

- 엔티티, 롬복 사용 @Entity @Getter @Setter

 

- 구분 컬럼 Dtype에 저장할 값 @DiscriminatorValue("A")

 

- Item에 상속됨 @~extends Item

  •  필드 생성 private ~
    • artist, etc

Book [ src - java - jpabook.jpashop - domain - item - Book ]

- 엔티티, 롬복 사용 @Entity @Getter @Setter

 

- 구분 컬럼 Dtype에 저장할 값 @DiscriminatorValue("B")

 

- Item에 상속됨 @~extends Item

  •  필드 생성 private ~
    • author, isbn

Movie [ src - java - jpabook.jpashop - domain - item - Movie ]

- 엔티티, 롬복 사용 @Entity @Getter @Setter

 

- 구분 컬럼 Dtype에 저장할 값 @DiscriminatorValue("M")

 

- Item에 상속 @~extends Item

  •  필드 생성 private ~
    • director, actor

8) Delivery [ src - java - jpabook.jpashop - domain -  Delivery ]

 

- 엔티티, 롬복 사용 @Entity @Getter @Setter

- 기본키 생성 및 전략 @Id @GeneratedValue

 

테이블의 컬럼과 연결될 대상에 '표시' @Column(name = "delivery_id")

  • 테이블(클래스)의 ID와 외래키 컬럼의 이름을 동일하게 맞춰주기 위해
  •  필드 생성 private ~
    • id 

- 1 : 1 관계 @OneToOne(mapped by = "delivery")

  • 1:1 관계는 FK 어디에 둬도 상관없지만 주로 엑세스 많이 하는 곳에 두기
  • delivery 연관관계 주인X / order에서 가져다 씀 = mappedBy사용
  • 필드 생성 private ~
    • Order order

- JPA 내장 타입 (사용하는 곳에 표시) @Embedded → Address

  • 위처럼 쓰든지 address 클래스가서 @Embeddable 쓰든지 둘 중 하나만 써도 괜춘
  • 필드 생성 private ~
    • Address address

enum 타입을 매핑 @Enumerated(EnumType.STRING) 

  • EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
    EnumType.STRING : enum 이름을 데이터베이스에 저장
  • 필드 생성 private ~
    • Deliverystatus deliverystatus

9) Category [ src - java - jpabook.jpashop - domain -  Category ]

 

- 엔티티, 롬복 사용 @Entity @Getter @Setter

- 기본키 생성 및 전략 @Id @GeneratedValue

 

테이블의 컬럼과 연결될 대상에 '표시' @Column(name = "category_id")

  • 테이블(클래스)의 ID와 외래키 컬럼의 이름을 동일하게 맞춰주기 위해
  •  필드 생성 private ~
    • id, name

N : N 관계 @ManyToMany

FK @JoinTable(name = "category_item")

  • 외의 코드는 현업에서 안쓰기 땜에 다 적지 않았음 (N:N 은 참고만 하고 사실상 볼 필요없음)
  •  필드 생성 private ~
    • items(list)

- 연관 관계 설정

 

10) 실행 결과 [src - java - jpabook.jpashop -CJpaShopApplication ]

 

 

 

 

[출처] 김영한 강사님 인프런 스프링 JPA 1편

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1

 

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 - 인프런 | 강의

실무에 가까운 예제로, 스프링 부트와 JPA를 활용해서 웹 애플리케이션을 설계하고 개발합니다. 이 과정을 통해 스프링 부트와 JPA를 실무에서 어떻게 활용해야 하는지 이해할 수 있습니다., 스프

www.inflearn.com