Spring Boot와 JPA 활용1 - TIL(1)

YulHee Kim·2021년 9월 20일
1

Spring Boot와 JPA 활용

목록 보기
1/11
post-thumbnail

[ 참고 강의 ] 실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발

💡 프로젝트 환경설정

✏️ JPA와 DB 설정, 동작확인

`main/resources/application.yml

spring:
  datasource:
    url: jdbc:h2:tcp://localhost/~/jpashop
    username: sa
    password:
    driver-class-name: org.h2.Driver

  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        format_sql: true

logging.level:
  org.hibernate.SQL: debug
  org.hibernate.type: trace
  • spring.jpa.hibernate.ddl-auto: create
    : 이 옵션은 애플리케이션 실행 시점에 테이블을 drop 하고, 다시 생성한다.

💡 도메인 분석 설계

✏️ 요구사항 분석

기능 목록

  • 회원 기능
    • 회원 등록
    • 회원 조회
  • 상품 기능
    • 상품 등록
    • 상품 조회
    • 상품 수정
  • 주문 기능
    • 상품 주문
    • 주문 내역 조회
    • 주문 취소
  • 기타 요구사항
    • 상품은 재고 관리가 필요하다
    • 상품을 카테고리로 구분할 수 있다
    • 상품 주문시 배송 정보를 입력할 수 있다.

✏️ 도메인 모델과 테이블 설계

회원, 주문, 상품의 관계 : 회원은 여러 상품을 주문할 수 있고 한번 주문할 때 여러 상품을 선택할 수 있으므로 주문과 상품은 다대다 관계다. 하지만 이런 다대다 관계는 관계형 데이터베이스는 물론이고 엔티티에서도 거의 사용하지 않는다. 따라서 그림처럼 주문상품이라는 엔티티를 추가해서 다대다 관계를 일대다, 다대일 관계로 풀어냈다.

상품 분류 : 상품은 도서,음반,영화로 구분되는데 상품이라는 공통 속성을 사용하므로 상속 구조로 표현했다.

회원 엔티티 분석

주문(Order): 한번 주문시 여러 상품을 주문할 수 있으므로 주문과 주문상품(OrderItem)은 일대다 관계다. 주문은 상품을 주문한 회원과 배송 정보, 주문 날짜, 주문 상태(status)를 가지고 있다. 주문 상태는 열거형을 사용했는데 주문(ORDER), 취소(CANCEL)을 표현할 수 있다.

배송(Delivery): 주문시 하나의 배송 정보를 생성한다. 주문과 배송은 일대일 관계다.

카테고리(Category): 상품과 다대다 관계를 맺는다. parent , child 로 부모, 자식 카테고리를 연결한
다.

회원 테이블 분석

MEMBER : 회원 엔티티의 Address 임베디드 타입 정보가 회원 테이블에 그대로 들어갔다. DELIVERY 테이블도 마찬가지다.

ITEM : 앨범, 도서, 영화 타입을 통합해서 하나의 테이블로 만들었다. DTYPE 컬럼으로 타입을 구분한다.

연관관계 매핑 분석

- 회원과 주문: 일대다, 다대일의 양방향 관계다. 따라서 연관관계의 주인을 정해야 하는데, 외래키가 있는 주문을 연관관계의 주인으로 정하는 것이 좋다.
그러므로 Order.member 를 ORDERS.MEMBER_ID 외래 키와 매핑한다.

- 주문상품과 주문: 다대일 양방향 관계다. 외래 키가 주문상품에 있으므로 주문상품이 연관관계의 주인이다.

- 주문상품과 상품: 다대일 단방향 관계다. OrderItem.item을 ORDER_ITEM.ITEM_ID 외래 키와 매핑한 다.

- 주문과 배송: 일대일 양방향 관계다. Order.delivery 를 ORDERS.DELIVERY_ID 외래 키와 매핑한다.

- 카테고리와 상품: @ManyToMany 를 사용해서 매핑한다.(실무에서 @ManyToMany는 사용하지 말자.)

✏️ 엔티티 클래스 개발

  • 실무에서는 가급적 Getter는 열어두고, Setter는 꼭 필요한 경우에만 사용하는 것을 추천

회원 엔티티

@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 를 사용했다.
테이블은 관례상 테이블명 + id 를 많이 사용한다.

주문 엔티티

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

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

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Member member;

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

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "delivery_id")
    private Delivery delivery;

    private LocalDateTime orderDate; // 주문시간

    @Enumerated(EnumType.STRING)
    private OrderStatus status; // 주문 상태 [ORDER, CANCEL]

    //연관관계 메서드
    public void setMember(Member member) {
        this.member = member;
        member.getOrders().add(this);
    }

    public void addOrderItem(OrderItem orderItem) {
        orderItems.add(orderItem);
        orderItem.setOrder(this);
    }

    public void setDelivery(Delivery delivery) {
        this.delivery = delivery;
        delivery.setOrder(this);
    }
}

주문 상태에 Enumerated 애노테이션을 선언했다.
EnumType은 INT가 아니라 되도록 STRING으로 사용하자.

주문 상태

package jpabook.jpashop.domain;

public enum OrderStatus {
    ORDER, CANCEL
}

다음 글에서 상품, 배송, 카테고리 엔티티의 코드를 적어보고, 엔티티 설계시 주의점에 대해 알아보겠습니당~

profile
백엔드 개발자

0개의 댓글