본문 바로가기
Dev/JPA

[JPA] 실습 - 요구사항 분석과 기본 매핑

by dev_jsk 2021. 8. 3.
728x90
반응형

요구사항 분석

  • 회원은 상품을 주문할 수 있다.
  • 주문 시 여러 종류의 상품을 선택할 수 있다.

도메인 모델 분석

  • 회원 - 주문 관계 : 회원은 여러번 주문할 수 있다. (1:N)
  • 주문 - 상품 관계 : 주문할 때 여러 상품을 선택할 수 있다. 반대로 같은 상품도 여러번 주문될 수 있다. 따라서 주문과 상품 사이에 주문상픔이라는 모델을 만들어서 주문 - 상품 의 N:M 관계를 주문 - 주문상품 으로 1:N, 주문상품 - 상품 으로 1:N 의 관계로 만들어 준다.

테이블 및 엔티티 설계

테이블 설계(좌측) / 엔티티 설계(우측)

실습

Entity

- Member.java

@Entity
public class Member {

    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
    private String name;
    private String city;
    private String street;
    private String zipcode;

    // getter, setter
}

- Order.java

@Entity
@Table(name = "ORDERS")
public class Order {
    
    @Id @GeneratedValue
    @Column(name = "ORDER_ID")
    private Long id;

    @Column(name = "MEMBER_ID")
    private Long memberId;  // 외래키를 그대로 필드로 사용하는 것이 아닌 Member 객체를 가져오도록 구현 필요

    // 객체를 가져와 사용하도록 구현해야 객체 중심 설계
    // Member member;
    // public Member getMember() {
    //     return member;
    // }
    // public void setMember(Member member) {
    //     this.member = member;
    // }

    private LocalDateTime orderDate;

    @Enumerated(EnumType.STRING)
    private OrderStatus status;

    // getter, setter
    
}

- OrderItem.java

@Entity
public class OrderItem {
    
    @Id @GeneratedValue
    @Column(name = "ORDER_ITEM_ID")
    private Long id;

    @Column(name = "ORDER_ID")
    private Long orderId;

    @Column(name = "ITEM_ID")
    private Long itemId;

    private int orderPrice;
    private int count;

    // getter, setter
}

- Item.java

@Entity
public class Item {
    
    @Id @GeneratedValue
    @Column(name = "ITEM_ID")
    private Long id;

    private String name;
    private int price;
    private int stockQuantity;

    // getter, setter
}

- OrderStatus.java (enum)

public enum OrderStatus {
    ORDER, CANCEL;
}

※ JPA 관례로 필드명 그대로 컬럼명이 생성되지만 스프링부트로 JPA 실행 시 Java의 낙타봉 표기를 소문자 언더스코어로 자동 변경되어 컬럼명이 생성된다.

Main

- JpaMain.java

public class JpaMain 
{
    public static void main( String[] args )
    {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {

            // 1. 테이블 설계에 맞춘 방식
            // Order order = em.find(Order.class, 1L);
            // Member member = em.find(Member.class, order.getMemberId());

            // 2. 객체 설계에 맞춘 방식
            // Order order = em.find(Order.class, 1L);
            // Member findMember = order.getMember():

            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }

        emf.close();
    }
}

DDL 동작 결과

DDL 실행 로그 및 결과, DB 구조

데이터 중심 설계의 문제점

  • 위 실습 방식은 객체 설계를 테이블 설계에 맞춘 방식 (ORDER 와 MEMBER 관계)
  • 테이블의 외래키를 객체에 그대로 가져옴
  • 객체 그래프 탐색 불가
  • 참조가 없으므로 UML도 잘못됨

따라서 Order 객체 구성 시 memberId를 필드로 선언하는 것이 아닌 Member 객체를 필드로 선언하여 해당 객체를 가져와 사용하는 방식으로 설계해야 한다.

728x90
반응형

'Dev > JPA' 카테고리의 다른 글

[JPA] 실습 - 연관관계 매핑 시작  (0) 2021.08.18
[JPA] 연관관계 매핑 기초  (0) 2021.08.12
[JPA] 엔티티 매핑  (0) 2021.08.02
[JPA] 영속성 관리  (0) 2021.07.20
[JPA] JPA 시작하기  (0) 2021.07.17

댓글