도메인 모델과 리포지터리를 구현할 때 선호하는 기술은 JPA다.
데이터 보관소로 RDBMS를 사용할 때, 객체 기반의 도멘 모델과 관계형 데이터 모델 간의 매핑을 처리하는 기술로 ORM 만한 것이 없다.
4.1 JPA를 이용한 리포지터리 구현
모듈 위치
- 리포지터리의 인터페이스는 애그리거트와 같이 도메인 영역에 속한다.
- 리포지터리를 구현한 클래스는 인프라스트럭처 영역에 속한다.
- 리포지터리 구현 클래스를 인프라스트럭처 영역에 위치시켜 인프라스트럭처에 대한 의존을 낮춰야 한다.
리포지터리 기본 기능 구현
- ID로 애그리거트 조회하기
- 애그리거트 저장하기
조회 시 해당 애그리거트가 존재 하지 않으면 Null 을 반환한다. null을 반환하고 싶지 않으면 Optional을 사용해도 좋다.
- 애그리거트를 수정한 결과를 저장소에 반영하는 메서드를 추가할 필요는 없다.
- 즉, 수정후에 save()나 merge() 를 하지 않아도 된다.
- 트랜잭션 범위에서 변경한 데이터를 커밋이 끝나는 시점에 DB에 반영하기 때문이다.
- 이를 Dirty Checking 이라 한다.
노트
- 삭제 기능이 있더라도 데이터를 실제로 삭제하는 경우는 많지 않다.
- 관리자 기능에서 삭제한 데이터까지 조회해야 하는 경우도 있고
- 데이터 원복을 위해 일정 기간 동안 보관해야 할 때도 있기 때문이다.
- 삭제하기 보단 삭제 플래그를 사용해서 데이터를 화면에 보여줄지 여부를 결정하는 방식으로 구현한다.
4.2 스프링 데이터 JPA를 이용한 리포지터리 구현
- 스프링에서 JPA 리포지터리 인터페이스를 구현한 객체를 Bean으로 등록해준다.
- 개발자는 손쉽게 리포지터리를 정의할 수 있다.
- 스프링 JPA 리포지터리를 사용하면 지정한 규칙에 맞게 메서드를 작성해야 한다.
- jpa query Method reference 참조
4.3 매핑 구현
- 애그리거트와 JPA 매핑을 위한 기본 규칙
- 애그리거트 루트는 엔티티이므로 @Entity로 매핑 설정한다.
- 한 테이블에 엔티티와 밸류 데이터가 같이 있다면
- 밸류는 @Embeddable로 매핑 설정한다.
- 밸류 타입 프로퍼티는 @Embedded로 매핑 설정한다.
- @Embeddable 타입에 설정한 칼럼 이름과 실제 칼럼 이름이 다르므로 @AttributeOverrides 애너테이션을 이용해 칼럼 이름을 변경할 수 있다.
기본 생성자
- JPA에서 매핑 스펙에는 기본 생성자가 포함한다.
- 불변 객체인 밸류 타입을 매핑할 때도 기본 생성자가 필요하며 이를 접근제어자 protected로 바꾸어 다른 코드에서 기본 생성자를 사용하지 못하도록 선언한다.
필드 접근 방식 사용
- private 필드를 접근 하려면 getter()/setter() 메서드가 필요하다.
- 하지만 위의 메서드는 캡슐화를 깨뜨린다.
- 객체의 행동에 의미를 잘 드러난 메서드를 사용해야 한다.
- 예를 들어 setState() 가 아닌 cancel() 로 사용해야 한다.
메모
- Hibernate에서 @ID나 @EmbeddedID가 어디에 위치했느냐에 따라 접근 방식을 결정한다.
- @ID나 @EmbeddedID 가 필드에 있으면 필드 접근 방식을 선택하고
- get 메서드에 위치하면 @Access를 이용해 메서드 접근 방식을 선택한다.
두 개 이상 프로퍼티를 한 개 칼럼에 매핑해야 할 떄
- AttributeConverter 인터페이스를 사용
- 인터페이스를 구현하고 @Converter 애너테이션을 적용한다.
- 속성 autoApply
- true 로 설정하면 entity로 매핑된 모든 모델의 컨버터 설정을 한 밸류타입에 대해 자동적으로 적용한다.
밸류 컬렉션을 별도 테이블로 매핑
- @ElementCollection과 @CollectionTable을 함께 사용
- @OrderColumn 으로 지정한 컬럼에 리스트의 인덱스 값을 지정
- @CollectionTable 밸류를 저장할 테이블을 지정
밸류 컬렉션을 한 개 컬럼 매핑
- AttributeConverter 인터페이스를 사용
- 인터페이스를 구현하고 @Converter 애너테이션을 적용한다.
- 해당 컬럼 타입으로 변환하여 저장
밸류를 이용한 ID 매핑
- 식별자라는 의미를 부각시키기 위해 식별자 자체를 밸류 타입으로 만들 수 있다.
- 식별자를 밸류타입으로 지정하려면
- Serializable 타입이여야 한다.
- 즉, Serializable 인터페이스를 상속해야 한다.
- Serializable 타입이여야 한다.
상속 구조 매핑
- @Ingeritance 애너테이션 적용
- 테이블 전략 설정이 여러 개 있다.
4.4 애그리거트 로딩 전략
- 애그리거트 루트를 로딩하면 루트에 속한 모든 객체가 완전한 상태여야 한다.
- 즉시로딩 (FetchType.EAGER)
- 애그리거트 루트를 조회 시점에 연관 된 애그리거트의 상태가 완전한 상태다.
- 지연로딩 (FetchType.LAZY)
- 애그리거트 루트를 조회 시점에 연관 된 애그리거트의 상태가 완전한 상태가 아니다.
- 연관 된 애그리거트를 가져와 사용시에 완전한 상태가 된다.
4.5 애그리거트의 영속성 전파
- 애그리거트 루트를 조회할 때뿐만 아니라 저장하고 삭제할 때도 하나로 처리해야 함을 의미한다.
4.6 식별자 생성 기능
- 식별자는 크게 세 가지 방식 중 하나로 생성
- 사용자가 직접 생성
- 도메인 로직으로 생성
- DB를 이용한 일련번호 생성
'Book > 도메인 주도 계발 시작하기' 카테고리의 다른 글
애그리거트 트랜잭션 관리 (1) | 2022.12.28 |
---|---|
도메인 서비스 (0) | 2022.12.28 |
스프링 데이터 JPA를 이용한 조회 기능 (0) | 2022.12.26 |
응용 서비스와 표현 영역 (0) | 2022.12.26 |
애그리거트 (0) | 2022.12.21 |
아키텍처 개요 (0) | 2022.12.21 |
도메인 모델 시작하기 (0) | 2022.12.20 |