일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 자바ORM표준프로그래밍
- SpringBoot
- anyMatch
- ERROR TYPE : org.apache.ibatis.binding.BindingException
- 데이터베이스 방언
- Invalid bound statement (not found)
- initialDelay
- Git
- http
- 매핑정보가없는필드
- hibernate.dialect
- 네이버 연결된 서비스
- HTTP3
- fixedDelay
- 멱등활용
- 네이버로그인API
- RFC723x
- 캐쉬가능
- HTTPMESSAGE
- @Entity
- org.apache.ibatis.binding.BindingException
- JPA
- gitreset
- @Table
- Transaction not successfully started
- DB방언
- 김영한JPA
- gitrevert
- 무상태프로토콜
- KAKAOLOGINAPI
- Today
- Total
twocowsong
[실전 예제] 요구사항 분석과 기본 매핑 본문
깃허브 정리 URL : https://github.com/sWineTake/jpa.git
직접 코딩하면서 예제를 순서대로 따라오는것을 권장합니다.
먼저 요구사항을 분석하고 도메인 모델과 테이블을 설계합니다.
요구사항 분석
- 회원은 상품을 주문할 수 있습니다.
- 주문 시 여러 종류의 상품을 선택할 수 있습니다.
요구사항을 분석해서 만든 메인화면 기능은 아래와같습니다.
- 회원기능 : 회원 등록, 회원 조회
- 상품기능 : 상품 등록, 상품 수정, 상품 조회
- 주문기능 : 상품 주문, 주문 내역 조회, 주문 취소
요구사항을 분석해보니 회원, 주문 상품 그리고 주문 상품이라는 엔티티가 도출되었습니다.
회원과 주문의 관계 : 회원은 여러번의 주문이 가능함으로 1 : N 관계입니다.
주문과 상품의 관계 : 주문할 때 여러 상품을 함께 선택할 수 있고, 같은 상품도 여러 번 주문될 수 있으므로 둘은 N : M 관계입니다. 하지만 이런 N : M 관계는 관계형 DB에서 물론이고 엔티티에서도 거의 사용하지않습니다.
따라서 주문상품이라는 연결 엔티티를 추가해서 N : M 관계를 1 : 1 , 1 : N 관계로 풀어냈습니다.
주문 상품에는 해당 상품을 구매한 금액과 수량 정보가 포함되어있습니다.
요구사항을 기반으로 테이블이 도출되었습니다.
엔티티를 생성해보겠습니다.
@Getter
@Setter
@Table(name = "MEMBER")
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "MEMBER_ID")
private Long id;
@Column
private String name;
@Column
private String city;
@Column
private String street;
@Column
private String zipcode;
}
@Entity
@Table(name = "ORDERS")
@Getter
@Setter
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ORDER_ID")
private Long id;
@Column(name = "MEMBER_ID")
private Long memberId;
@Temporal(TemporalType.TIMESTAMP)
private Date orderDate;
@Enumerated(EnumType.STRING)
private OrderStatus orderStatus;
}
public enum OrderStatus {
ORDER, CANCEL
}
@Entity
@Getter
@Setter
@Table(name = "ORDER_ITEM")
public class OrderItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ORDER_ITEM_ID")
private Long id;
@Column(name = "ORDER_ID")
private Long orderId;
@Column(name = "ITEM_ID")
private Long itemId;
@Column(name = "ORDER_PRICE")
private int orderPrice;
private int count;
}
@Entity
@Setter
@Getter
@Table(name = "ITEM")
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ITEM_ID")
private Long id;
private String name;
private int price;
@Column(name = "STOCK_QUANTITY")
private int stockQuantity;
}
서적에서는 @GeneratedValue의 기본값인 AUTO로 생성하였지만 저는 GenerationType.IDENTITY로 생성하였습니다.
지금 이 방식은 객체 설계를 테이블 설계에 맞춘 방법입니다.
특히 테이블의 오래키를 객체에 그대로 가져온 부분이 문제입니다.
왜냐하면 관계형 DB는 연관 된 객체를 찾을 때 외래 키를 사용해서 조인하면 되지만 객체에는 조인이라는 기능이 없습니다. 객체는 연관된 객체를 찾을 때 참조를 사용해야 합니다.
객체에서 참조 대신에 DB의 외래키를 그대로 가지고 있으므로 order.getMember() 처럼 객체 그래프를 탐색할 수 없고 객체의 특성도 살릴 수 없습니다.
이렇게 외래키만 가지고 있으면 연관된 엔티티를 찾을 때 외래키로 DB를 다시 조회해야합니다.
예를들어 주문을 조회한 다음 주문과 연관된 호원을 조회하려면 다음처럼 외래키를 사용해서 다시 조회해야합니다.
String orderId = "orderId";
// 주문 번호로 주문 정보 조회
Order order = em.find(Order.class, orderId);
// 외래키로 다시 회원 정보 조회
Member member = em.find(Member.class, order.getMemberId());
객체는 참조를 사용해서 연관관계를 조회할 수 있습니다.
따라서 다음처럼 참조를 사용하는것이 객체지향적인 방법입니다.
String orderId = "orderId";
// 주문 번호로 주문 정보 조회
Order order = em.find(Order.class, orderId);
Member member = order.getMember();
정리하자면 객체는 참조를 사용해서 연관된 객체를 찾고 테이블은 외래키를 사용해서 연관된 테이블을 찾으므로 둘 사이에는 큰 차이가 있습니다.
JPA는 객체의 참조와 테이블의 외래키를 매핑해서 객체에서는 참조를 사용하고 테이블에서는 외래키를 사용할 수 있도록 합니다. 이제부터 참조와 외래키를 매핑하는방법을 천천히 알아보겠습니다.
'IT > JPA' 카테고리의 다른 글
객체 연관관계와 테이블의 연관관계 (0) | 2022.05.25 |
---|---|
연관관계 매핑 기초 (0) | 2022.05.23 |
중간 정리 (0) | 2022.05.21 |
@Transient (0) | 2022.05.21 |
@Lob (0) | 2022.05.21 |