본문 바로가기

[DDD START!] 4장. 리포지터리와 모델구현(JPA 중심)

- JPA를 이용한 리포지터리 기능 구현

- 엔티티와 밸류 매핑

- 밸류 컬렉션 매핑

- 애그리거트 로딩 전략과 영속성 전파

- 식별자 생성 기능

 

모듈위치

리포지터리 인터페이스 -> 애그리거트와 같은 도메인 영역

리포지터리 구현 클래스 -> 인프라스트럭처 영역

리포지터리 기본 기능 구현

1. 아이디로 애그리거트 조회하기

2. 애그리거트 저장하기

인터페이스는 애그리거트 루트를 기준으로 작성

-> 주문 애그리거트는 Order(루트 엔티티), OrderLine, Orderer, ShippingInfo 등이 있지만, Order를 기준으로 작성.

 

 

기본생성자

엔티티와 밸류의 생성자는 객체를 생성할 때 필요한 것을 전달받는다. 

Receiver (밸류)가 불변 타입이면 생성 시점에서 필요한 값을 모두 전달 받으므로 값을 변경하는 set 메서드 제공x

-> 기본 생성자 추가할 필요 없음

-> 하지만 JPA @Entity, @Embeddable로 클래스를 매핑하려면 기본 생성자를 제공해야함!

∴ Receiver와 같은 불변 타입은 기본 생성자가 필요 없음에도 불구하고 기본 생성자를 추가해야 함!!

기본 생성자는 JPA 프로바이더가 객체를 생성할 때만 사용한다. 다른 코드에서 사용하지 못하도록 protected로 선언

 

필드 접근 방식 사용

JPA는 필드와 메서드의 두 가지 방식으로 매핑 처리 가능.

1. 메서드

-> 프로퍼티를 위한 get, set 메서드 구현 해야 함

-> 엔티티가 객체로서 제 역할을 하려면 set 메서드 대신, 의도가 잘 드러나는 기능을 제공해야 함.

-> 밸류 타입을 불변으로 구현하고 싶은 경우 set 메서드 자체가 필요 없는데 JPA 구현 때문에 공개 set을 추가하는건 좋지 않음.

∴ JPA 매핑 처리를 프로퍼티 방식이 아닌 필드 방식으로 선택해서 불필요한 get/set 메서드를 구현하지 말아야 함!!

 

AttributeConverter를 이용한 밸류 매핑 처리

int, long, String, LocalDate와 같은 타입은 DB테이블의 한개 칼럼과 매핑된다.

밸류 타입의 프로퍼티를 한개 칼럼에 매핑해야 할 때도 있다. 

ex) Length가 길이값과 단위 두 프로퍼티를 갖고 있는데 DB 테이블에는 한 개 칼럼에 1000mm와 같은 형식으로 저장 가능

public class Length {
	private int value;
    private String unit;
}

-> 1000mm 로 저장 

WIDTH VARCHAR(20)

@Converter autyApply 속성 기본값 false -> 프로퍼티 값을 변환할 때 사용할 컨버터를 직접 지정할 수 있음.

@Converter autyApply 속성 true -> 모델에 출현하는 모든 Money타입의 프로퍼티에 대해 MoneyConverter를 자동으로 적용.

 

밸류 컬렉션: 별도 테이블 매핑

@ElementCollection

@CollectionTable

 

밸류 컬렉션 : 한 개 컬럼 매핑

AttributeConverter

 

밸류를 이용한 아이디 매핑

식별자라는 의미를 부각시키기 위해 식별자 자체를 별도 밸류 타입으로 만들 수 있다. 

ex) OrderId, MemberId,

밸류 타입을 식별자로 매핑하면 @Id 대신 @EmbeddedId 애노테이션을 사용한다.

JPA에서는 식별자 타입은 Serializable 타입-> Serializable 인터페이스를 상속 받아야 함.

밸류 타입으로 식별자를 구현할 때 얻을 수 있는 장점

1. 식별자에 기능을 추가할 수 있음.

 

별도 테이블에 저장하는 밸류 매핑

애그리거트에서 루트 엔티티를 뺀 나머지 구성 요소는 대부분 밸류이다.

자신만의 독자적인 라이프사이클을 갖는다면 다른 애그리거트일 가능성이 높음.

ex) 상품과 상품 리뷰는 같은 라이프사이클이 아님. 각각의 변경이 각각에게 영향을 주지 않음.

애그리거트에 속한 객체가 밸류인지 엔티티인지를 구분하는 방법은 고유 식별자를 갖는지 여부 확인.

@SecondaryTable

@AttributeOverride

 

밸류 컬렉션을 @Entity로 매핑하기

JPA는 @Embeddable 타입의 클래스 상속 매핑을 지원하지 않음 -> @Entity로 상속 매핑해야 함.

 

애그리거트 로딩 전략

JPA 매핑을 설정할 때 기억해야 할 점은 애그리거트에 속한 객체가 모두 모여야 완전한 하나가 된다는 것.

조회 시점에서 애그리거트를 완전한 상태가 되도록 하려면 애그리거트 루트 연관 조회 방식을 즉시 로딩(FetchType.EAGER)으로 설정.

 

애그리거트의 영속성 전파

저장 메서드는 애그리거트 루트만 저장하면 안 되고 애그리거트에 속한 모든 객체를 저장해야 한다. 

삭제 메서드는 애그리거트 루트 뿐만 아니라 애그리거트에 속한 모든 객체를 삭제해야 한다. 

@Entity타입에 대한 매핑은 casede 속성을 사용해서 저장과 삭제시에 함께 처리되도록 설정.

 

식별자 생성 기능