인프런 강의
🔗 김영한 - 실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
도메인 모델과 분석 설계
요구사항 분석
- 회원은 여러 상품을 주문할 수 있다.
- 주문 <-> 상품 : 다대다 관계 = 1번 주문 시, 여러 상품 선택할 수 있다.
주문 상품이라는 엔티티를 추가하여, 다대다 관계를 일대다 / 다대일 관계로 풀어냄
- 상품 분류 : 상품이라는 공통 속성을 사용하므로 상속 구조로 표현
회원 엔티티 분석
- 회원(Member): 이름과 임베디드 타입인 주소(Address), 그리고 주문(orders) 리스트를 가진다.
- 주문(Order): 한 번 주문시 여러 상품을 주문할 수 있으므로 주문과 주문상품(OrderItem)은 일대다관계다.주문은 상품을 주문한 회원과 배송 정보, 주문 날짜, 주문 상태(status)를 가지고 있다. 주문상태는 열거형을 사용했는데 주문(ORDER), 취소(CANCEL)을 표현할 수 있다.
- 주문상품(OrderItem): 주문한 상품 정보와 주문 금액(orderPrice), 주문 수량(count) 정보를 가지고있다.(보통 OrderLine , LineItem 으로 많이 표현한다.)
- 상품(Item): 이름, 가격, 재고수량(stockQuantity)을 가지고 있다. 상품을 주문하면 재고수량이 줄어든다. 상품의 종류로는 도서, 음반, 영화가 있는데 각각은 사용하는 속성이 조금씩 다르다.
- 배송(Delivery): 주문시 하나의 배송 정보를 생성한다. 주문과 배송은 일대일 관계다.
- 카테고리(Category): 상품과 다대다 관계를 맺는다. parent, child로 부모, 자식 카테고리를 연결한다.
- 주소(Address): 값 타입(임베디드 타입)이다. 회원과 배송(Delivery)에서 사용한다.
회원 테이블 분석
- MEMBER: 회원 엔티티의 Address 임베디드 타입 정보가 회원 테이블에 그대로 들어갔다. 이것은DELIVERY 테이블도 마찬가지다.
- ITEM: 앨범, 도서, 영화 타입을 통합해서 하나의 테이블로 만들었다. DTYPE 컬럼으로 타입을 구분한다.
연관관계 매핑분석
- 회원과 주문: 일대다 , 다대일의 양방향 관계다.따라서 연관관계의 주인을 정해야 하는데, 외래 키가 있는 주문을 연관관계의 주인으로 정하는 것이 좋다. 그러므로 Order.member 를 ORDERS.MEMBER_ID 외래키와 매핑한다.
- 주문상품과 주문: 다대일 양방향 관계다. 외래 키가 주문상품에 있으므로 주문상품이 연관관계의 주인이다. 그러므로 OrderItem.order 를 ORDER_ITEM.ORDER_ID 외래 키와 매핑한다.
- 주문상품과 상품: 다대일 단방향 관계다. OrderItem.item 을 ORDER_ITEM.ITEM_ID 외래 키와
매핑한다.
- 주문과 배송: 일대일 양방향 관계다. Order.delivery 를 ORDERS.DELIVERY_ID 외래 키와 매핑한다.
- 카테고리와 상품: @ManyToMany 를 사용해서 매핑한다.(다대다 관계를 예제로 보여주기 위해 추가)
엔티티 설계 시 주의점
1. 엔티티에는 가급적 setter를 사용하지 말자
-> 변경 포인트가 많아서, 유지 보수가 어려움
2. 모든 연관관계는 지연로딩으로 설정
- 즉시로딩(EAGER)은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵다. 특히 JPQL을 실행할 때 N+1문제가 자주 발생
- 연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용
- @XToOne(OneToOne, ManyToOne) 관계는 기본이 즉시로딩이므로 직접 지연로딩으로 설정
ManyToOne(fetch = LAZY)
3. 컬렉션은 필드에서 초기화
테이블 컬럼명 생성 전략
하이버네이트 기존 구현 : 엔티티의 필드명을 그대로 테이블의 컬럼명으로 사용
1. 논리명 생성 : 명시적으로 컬럼, 테이블명을 직접 적지 않으면 ImplicitNamingStrategy 사용
spring.jpa.hibernate.naming.implicit-strategy : 테이블,컬럼명 명시하지 않을 때 논리명 적용
2. 물리명 적용 :
spring.jpa.hibernate.naming.physical-strategy : 모든 논리명에 적용됨, 실제 테이블에 적용