도메인 분석 설계
2023. 9. 29. 00:05ㆍLECTURES/실전! 스프링 부트와 JPA 활용
요구사항 분석
기능 목록
- 회원 기능
- 회원 등록
- 회원 조회
- 상품 기능
- 상품 등록
- 상품 수정
- 상품 조회
- 주문 기능
- 상품 주문
- 주문 내역 조회
- 주문 취소
- 기타 요구사항
- 상품은 재고 관리가 필요하다.
- 상품의 종류는 도서, 음반, 영화가 있다.
- 상품을 카테고리로 구분할 수 있다.
- 상품 주문시 배송 정보를 입력할 수 있다.
도메인 모델과 테이블 설계
- 데이터베이스가
order by
때문에order
를 예약어로 잡고 있기 때문에 관례상Orders
를 많이 사용함
연관관계 매핑 분석
- 회원과 주문 : 일대다, 다대일의 양방향 관계
- 주문상품과 주문 : 다대일 양방향 관계
- 주문상품과 상품 : 다대일 단방향 관계
- 주문과 배송 : 일대일 양방향 관계
- 카테고리와 상품 :
@ManyToMany
로 매핑하면 되지만 실무에서는 이렇게 쓰면 안됨
외래 키가 있는 곳을 연관관계의 주인으로 정해라.
- 회원과 주문 :
Order.member
- 주문상품과 주문 :
OrderItem.order
- 주문상품과 상품 :
OrderItem.item
- 주문과 배송 :
Order.delivery
엔티티 클래스 개발
https://github.com/dpdms529/JpaShop/commit/a8318348cb42ce0049603d41210188e47ebe3260
- 예제에서는 Getter와 Setter를 모두 열어두었지만, 실무에서는 Getter만 열어두고, Setter는 필요한 경우에만 열어두는 것이 좋음
- Setter를 호출하면 데이터가 변하는데, 엔티티가 왜 변경되는지 추적하기 어려워짐
- Setter 대신 변경 지점이 명확하도록 변경을 위한 비즈니스 메서드를 별도로 제공해야 함
- PK 컬럼명은 관례상
테이블명_id
를 많이 사용함- 엔티티는 타입이 있기 때문에
id
만으로도 쉽게 구분이 가능하지만, 테이블은 타입이 없으므로 구분이 어렵기 때문
- 엔티티는 타입이 있기 때문에
@ManyToMany
는 가급적 사용 X- 중간 테이블에 컬럼을 추가할 수 없고, 세밀하게 쿼리를 실행하기 어려움
- 중간 엔티티를 만들고
@ManyToOne
,@OneToMany
로 매핑해서 사용하자
- 값 타입은 변경 불가능하게 설계해야 함
@Setter
를 제거하고, 생성자에서 값을 모두 초기화해서 변경 불가능한 클래스를 만들자- JPA 스펙상 엔티티나 임베디드 타입(
@Embeddable
)은 자바 기본 생성자를public
또는protected
로 설정해야 함protected
가public
보다 안전
- JPA 구현 라이브러리가 객체를 생성할때 리플랙션 같은 기술을 사용할 수 있도록 지원해야 하기 때문
엔티티 설계시 주의점
https://github.com/dpdms529/JpaShop/commit/7b864daf74c507540dbaef513f70038cd5e79842
엔티티에는 가급적 Setter를 사용하지 말자
- Setter가 열려있으면 변경 포인트가 너무 많아서 유지보수가 어려움
모든 연관관계는 지연로딩으로 설정
- 즉시로딩(
EAGER
)은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어려움, 특히 JPQL을 실행할 때 N+1 문제가 자주 발생 - 실무에서 모든 연관관계는 지연로딩(
LAZY
)으로 설정해야 함 - 연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join 또는 엔티티 그래프 기능을 사용
@XToOne(OneToOne, ManyToOne)
관계는 기본이 즉시로딩이므로 직접 지연로딩으로 설정해야 함
컬렉션은 필드에서 초기화 하자
- 필드에서 바로 초기화하면
null
문제에서 안전 - 하이버네이트는 엔티티를 영속화할 때 컬렉션을 감싸서 하이버네이트가 제공하는 내장 컬렉션으로 변경함
- 만약 임의의 메서드에서 컬렉션을 잘못 생성하면 하이버네이트 내부 매커니즘에 문제가 발생할 수 있음
테이블, 컬럼명 생성 전략
- 하이버네이트 기존 구현 : 엔티티의 필드명을 그대로 테이블의 컬럼명으로 사용
- 스프링 부트 신규 설정
- 카멜 케이스 -> 언더스코어
- . -> 언더스코어
- 대문자 -> 소문자
기타
casecade = CascadeType.ALL
- 하위 엔티티로 모든 작업을 전파
- 예) Order를 저장하면 Delivery도 저장됨
- 연관관계 메서드
- 양방향 관계일 때 연관관계 메서드를 사용하면 한 엔티티만 관계를 설정해줘도 다른 엔티티의 관계도 설정 가능
'LECTURES > 실전! 스프링 부트와 JPA 활용' 카테고리의 다른 글
주문 도메인 개발 (0) | 2023.09.29 |
---|---|
상품 도메인 개발 (0) | 2023.09.29 |
회원 도메인 개발 (0) | 2023.09.29 |
애플리케이션 구현 준비 (0) | 2023.09.29 |
프로젝트 환경설정 (0) | 2023.09.29 |