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

dbstmd·2023년 12월 19일
0

DDD

목록 보기
5/8

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

public interface OrderSummaryDao extends Repository<OrderSummary, String> {
    List<OrderSummary> findAll(Specification<OrderSummary> spec);
}
  • 별다른 구현 없이 스펙을 만족하는 엔티티 목록을 검색할 수 있다.

5.5 스펙 조합

스펙 조합 메서드
스프링 데이터 JPA의 스펙 인터페이스는 스펙을 조합할 수 있는 메서드 and, or를 제공한다.

  • and() 메서드는 두 스펙을 모두 충족하는 조건을 표현하는 스펙을 생성
  • or() 메서드는 두 스펙 중 하나 이상 충족하는 조건을 표현하는 스펙을 생성
Specification<OrderSummary> spec1 = OrderSummarySpecs.ordererId("user1");
Specification<OrderSummary> spec2 = OrderSummarySpecs.orderDateBetween(
        LocalDateTime.of(2022, 1, 1, 0, 0, 0),
        LocalDateTime.of(2022, 1, 2, 0, 0, 0)
);
Specification<OrderSummary> spec3 = spec1.and(spec2);

spec1.and(spec2)는 spec1과 spec2를 모두 충족하는 조건을 표현하는 spec3을 생성한다.

스펙 반대로 적용
스펙 인터페이스는 not() 메서드도 제공한다. not()은 조건을 반대로 적용할 때 사용한다.

Specification<OrderSummary> spec4 = Specification.not(spec1);

null check
null 가능성이 있는 스펙 객체와 다른 스펙을 조합해야 할 때가 있다. 이런 경우 NPE 방지를 위해 null 여부를 검사해야 하는데, 이 때 where() 메서드를 사용하면 편하다.

where() 메서드는 null을 전달하면 아무 조건도 생성하지 않는 스펙 객체를 리턴하고, null이 아니면 인자로 받은 스펙 객체 그대로 리턴한다.

Specification<OrderSummary> spec5 = Specification.where(spec1).and(spec2);

5.6 정렬 지정하기

두 가지 방법을 사용해서 정렬을 지정할 수 있다.

OrderBy
메서드 이름에 OrderBy를 사용해서 정렬을 지정할 수 있다.

public interface OrderSummaryDao extends Repository<OrderSummary, String> {
    List<OrderSummary> findByOrdererIdOrderByNumberDesc(String ordererId);
    List<OrderSummary> findByOrdererIdOrderByNumberDescOrderDateAsc(String ordererId); // 2개 프로퍼티 정렬
}

Sort

public interface OrderSummaryDao extends Repository<OrderSummary, String> {
    List<OrderSummary> findByOrdererId(String ordererId, Sort sort);
    List<OrderSummary> findAll(Specification<OrderSummary> spec, Sort sort);
}
Sort sort1 = Sort.by("number").ascending();
orderSummaryDao.findByOrdererId("user1", sort);

5.7 페이징 처리하기

스프링 데이터 JPA는 페이징 처리를 위해 Pageable 타입을 이용한다.
find 메서드에 Pageable 타입 파라미터를 사용하면 페이징을 자동으로 처리해준다.

public interface MemberDataDao extends Repository<MemberData, String> {
    List<MemberData> findByNameLike(String name, Pageable pageable);
}
PageRequest pageReq = PageRequest.of(1, 10);
List<MemberData> user = memberDataDao.findByNameLike("사용자%", pageReq);

Pageable 타입 객체는 PageRequest 클래스를 이용해 생성한다.

PageRequest.of() 첫 번째 인자는 페이지 번호를, 두 번째 인자는 한 페이지의 개수를 의미한다.

페이지는 0부터 시작 즉 1페이지의 데이터 10개를 조회한다.

PageRequest pageReq = PageRequest.of(1, 10, Sort.by("name").ascending());
List<MemberData> user = memberDataDao.findByNameLike("사용자%", pageReq);

PageRequest는 Sort를 사용해 정렬 순서를 지정할 수 있다.

public interface MemberDataDao extends Repository<MemberData, String> {
    Page<MemberData> findByBlocked(boolean blocked, Pageable pageable);
}

Pageable을 사용하는 메서드의 리턴 차입이 Page일 경우 스프링 데이터 JPA는 목록 조회 쿼리와 함께 COUNT쿼리도 실행해서 조건에 해당하는 데이터 개수를 구한다.

전체 개수, 페이지 개수 등 페이징 처리에 필요한 데이터도 함께 제공한다.

COUNT 쿼리 실행 조건

Page<MemberData> findByBlocked(boolean blocked, Pageable pageable);
List<MemberData> findByNameLike(String name, Pageable pageable);
List<MemberData> findAll(Specification<MemberData> spec, Pageable pageable);

Pageable 타입을 사용하더라도 리턴 타입이 List이면 Count 쿼리를 실행하지 않음.
반면에 spec을 사용하는 findAll 메서드에 Pageable 타입을 사용하면 리턴 타입이 Page가 아니라도 COUNT 쿼리를 실행함.

N개의 데이터 필요
처음부터 N개의 데이터가 필요하다면 Pageable을 사용하지 않고 findFirstN 형식의 메서드를 사용할 수 있다.

List<MemberData> findFirst3ByNameLikeOrderByName(String name);
profile
개인 학습용

0개의 댓글