DDD를 공부하다가 한 엔티티에 여러 객체들을 사용할 일이 많아져서 방법을 찾다가 @Embedded, @Embeddable 을 사용해야 한다는 것을 봤다.
이게 뭔지, 어떨 때 사용하는지 알아보자! 😎
주문 엔티티가 다음과 같다.
(참고로 도메인 주도 개발 중이기 때문에 엔티티 코드가 좀 더러워요..)
@Entity
@NoArgsConstructor
public class Order {
@EmbeddedId
private OrderId id;
private OrderState orderState;
@Embedded
private Orderer orderer;
@ElementCollection(fetch = FetchType.LAZY)
private List<OrderLine> orderLines;
@Embedded
private ShippingInfo shippingInfo;
@Convert(converter = MoneyConverter.class)
private Money totalAmounts;
public Order(OrderId id, Orderer orderer, List<OrderLine> orderLines,
ShippingInfo shippingInfo, OrderState orderState) {
setId(id);
setOrderer(orderer);
setOrderLines(orderLines);
setShippingInfo(shippingInfo);
this.orderState = orderState;
}
// 주요 메서드, ...
}
위의 코드를 보다시피 주문 엔티티에는 아래의 항목이 있다.
- 주문 고유 번호 : OrderId
- 주문 상태 : OrderState
- 주문자 : Orderer
- 주문 제품 : List<OrderLine>
- 배송지 정보 : ShippingInfo
(참고) 객체를 묶어서 사용하는 이유?
보통 배송지 정보를 주문 엔티티에서 사용할 땐, 위의 코드와 같은 컬럼 형태로 코드를 작성하면
@Entity
@NoArgsConstructor
public class Order {
...
// 배송지 주소
private String postalCode; // 우편번호
private String state; // 시/도
private String city; // 시/군/구
private String district; // 읍/면/동
private String streetAddress; // 상세주소
// 받는 사람
private String name;
private String phone;
// 주문 특이사항
private String message;
...
}
이런 식으로 하나하나 풀어서 나열하게 된다.
그런데 위의 방식은 가독성이 너무 떨어진다.
이러한 이유 때문에 객체로 각각 묶어서 사용하면 가독성을 높일 수 있다.
이럴 때 사용하는 것이 @Embedded, @Embeddable 이다.
@Embedded
- 임베디드 타입을 사용하기 위한 Entity에서 사용
- 데이터베이스 테이블의 한 열이 아닌 여러 열에 매핑되는 복합 값 타입을 나타냄
@Embeddable
- 임베디드 타입으로 사용하기 위해 생성한 Class에서 사용
그리고 단순한 컬럼 타입 말고 @EmbeddedId를 사용한다면 ID 컬럼도 충분히 객체로 사용할 수 있다.
그 대신 객체를 엔티티의 ID 컬럼 즉, 식별자로 사용한다면 이 컬럼을 복합키로 인식하게 된다.
@Entity
@NoArgsConstructor
public class Order {
@EmbeddedId
private OrderId id;
...
}
@Getter
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class OrderId implements Serializable {
private String id;
// 복합키일 경우 이 곳에 더 많은 컬럼이 들어올 수 있음
}
또한, 엔티티의 ID가 되는 객체는 반드시 Serializable 을 상속받아야 한다.
그 이유는 JPA가 엔티티를 식별할 때 이 복합 키를 직렬화 가능하게 만들어야 하기 때문이다.
영속성 컨텍스트는 엔티티의 PK 즉, 위의 OrderId와 같은 식별자를 사용해 엔티티를 관리한다.
그런데 이 영속성 컨텍스트에서 관리되는 모든 엔티티는 Serializable 을 구현해야 한다.
→ 무조건 Serializable 을 구현해야 하는 건 아니지만, JPA 표준 스펙은 엔티티에 Serializable 을 구현하도록 권장한다.
참고
https://www.inflearn.com/questions/16570/버그-문의드려봅니다
버그 문의드려봅니다. - 인프런
영한님 안녕하세요. 강좌들으면서 실무에서 직접 해보고 있는데 풀리지 않는 오류가 하나 등장했습니다. ManyToOne 단방향 맵핑한 영역이 있습니다. (MemberWebUser / MemberCompany) (다만, PK 가 아닌 Unique
www.inflearn.com
https://product.kyobobook.co.kr/detail/S000001810495
도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지 | 최범균 - 교보문고
도메인 주도 개발 시작하기: DDD 핵심 개념 정리부터 구현까지 | 가장 쉽게 배우는 도메인 주도 설계 입문서!이 책은 도메인 주도 설계(DDD)를 처음 배우는 개발자를 위한 책이다. 실제 업무에 DDD를
product.kyobobook.co.kr
'Spring > JPA' 카테고리의 다른 글
[JPA] Spring JPA 페이징 성능 향상 (2) | 2024.12.24 |
---|---|
[JPA] 여러 트랜잭션이 하나의 영속성 컨텍스트? (0) | 2024.07.31 |