본문 바로가기
Back-End/도메인 주도 개발 시작하기

[DDD] 도메인 주도 개발 시작하기_Ch5

by ChaSso 2023. 3. 23.

Chapter 5 스프링 데이터 JPA를 이용한 조회 기능

5.1 시작에 앞서

∘ CQRS : 명령 모델과 조회 모델을 분리하는 패턴

∘ 명령 모델 : 상태를 변경하는 기능 구현

∘ 조회 모델 : 데이터를 조회하는 기능

∘ 앞 부분에서 봤던 도메인 모델은 명령 모델로 주로 사용됨

∘ 정렬, 페이징, 검색 조건 지정과 같은 기능은 주문 목록, 상품 상세와 같은 조회 기능에 사용됨

 

5.2 검색을 위한 스펙

∘ 검색 조건의 조합마다 find를 정의하는 것은 좋지 않음

∘ 스펙 : 검색 조건을 다양하게 조합할 때 사용, 애그리거트가 특정 조건을 충족하는지를 검사할 때 사용하는 인터페이스

∘ 스펙을 리포지터리에 사용하는지, DAO에 사용하는지에 따라 검사 대상이 되는 객체가 다름

∘ isSatisfiedBy() : 검사 대상 객체가 조건을 만족하는지 만족하지 않는지 알려줌

∘ 리포지터리와 DAO는 검색 대상을 걸러내는 용도로 스펙을 사용함

∘ 특정 조건의 애그리거트를 검색하고 싶으면 스펙을 만들어서 리포지터리에 전달하면 됨

 

5.3 스프링 데이터 JPA를 이용한 스펙 구현

∘ Specification(스펙 인터페이스) : 스프링 데이터 JPA에서 검색 조건을 표현하기 위한 인터페이스

∘ 스펙마다 구현 클래스를 만들 필요 없이 별도 클래스에 스펙 생성 기능을 모아도 됨

∘ 스펙 인터페이스는 함수형 인터페이스여서 람다식을 이용해 객체를 생성할 수 있음

∘ 스펙 생성 기능을 제공하는 클래스를 이용해서 스펙 생성 코드를 작성할 수 있음

 

5.4 리포지터리/DAO에서 스펙 사용하기

∘ findAll() : 스펙을 충족하는 엔티티 검색하는 메서드. 스펙 인터페이스를 파라미터로 가짐.

 

5.5 스펙 조합

∘ 스펙 인터페이스는 스펙을 조합할 수 있는 and(), or()를 사용할 수 있음 ex. spec3=spec1.and(spec2)

∘ where()을 사용하면 null 여부를 매번 확인하지 않고도 비어 있는 스펙 객체를 거를 수 있음

 

5.6 정렬 지정하기

∘ 스프링 데이터 JPA는 메서드 이름에 OrderBy를 사용해서 정렬 기준을 지정하거나 Sort를 인자로 전달해서 정렬을 지정함

∘ findByOrderIdOrderByNumberDesc()orderId프로퍼티 값을 기준으로 검색 조건을 지정하고 number 프로퍼티 값에 대해 역순으로 정렬하도록 함

∘ 두 개 이상의 프로퍼티에 대해서 정렬 순서를 지정할 수 있음 ex. findByOrderIdByOrderDateDescNumberAsc∘ OrderDate에 대해 내림차순으로 정렬하고 Number 프로퍼티에 대해 오름차순으로 정렬함

∘ OrderBy를 사용하면 메서드 이름이 길어지므로 OrderBy를 사용하는 대신에 Sort 타입을 사용해도 됨

 

5.7 페이징 처리하기

∘ 페이징 처리 : 목록을 보여줄 때 전체 데이터 중 일부만 보여줌

∘ 스프링 데이터 JPA에서 find 메서드에 Pageable 타입 파라미터를 사용하면 자동으로 페이징 처리가 됨

∘ PageRequest.of(페이지번호, 한페이지의 개수)

∘ 정렬 순서를 지정할 수 있음

∘ Page 타입을 사용하면 COUNT를 이용해서 조건에 부합하는 개수를 구할 수 있음

∘ 조회할 개수를 미리 정해두고 불러올 수 있음

 

5.8 스펙 조합을 위한 스펙 빌더 클래스

∘ 복잡한 스펙 코드 조합 대신에 스펙 빌더를 이용해서 코드 작성

∘ 스펙 코드 빌더에는 and(), ifHasText(), ifTrue() 메서드가 있음

 

5.9 동적 인스턴스 생성

∘ JPA는 쿼리 결과에서 임의의 객체를 동적으로 생성하는 기능을 제공

∘ 동적 인스턴스는 객체 기준으로 쿼리를 작성하면서 로딩 방법과 같은 고민 없이 데이터를 원하는 대로 조회할 수 있음

 

5.10 하이버네이트 @Subselect 사용

∘ 하이버네이트가 지원하는 @Subselect는 쿼리 결과를 @Entity로 매핑할 수 있도록 함. 쿼리 결과를 테이블처럼 사용.

∘ 하이버네이트는 트랜잭션을 커밋할 때 DB에 반영하므로 반영되지 않은 상태에서 데이터 조회를 하는 경우 발생 -> @Synchronize 사용으로 해결. 변경 사항이 생기면 플러시 먼저 하도록.

∘ @Subselect가 붙은 @Entity도 일반 @Entity와 동일한 방법으로 조회 가능