반응형
조회 API에 여러 개의 동적 정렬 조건과 페이지네이션 기능이 필요할 때 Spring Data JPA로 쉽게 구현할 수 있다. 이건 단순히 게시글 목록을 조회하는 상황인데, 만약 더 복잡한 연관관계의 조회라면 이 방법은 좋지 않을 수 있으니 성능을 고려하자.
Controller
페이지네이션과 동적 정렬 조건을 쿼리 스트링으로 입력받는다. 정렬 조건은 sort=key,option 형식으로 입력 받는다고 설정했다. 예를 들면 /posts&sorts=createdAt,desc 같은 형식이다.
@GetMapping
public ResponseEntity<BaseResponse<List<PostFindAllResponse>>> findAll(
@RequestParam(defaultValue = "0", required = false) int page,
@RequestParam(defaultValue = "5", required = false) int size,
@RequestParam(required = false) List<String> sorts
) {
PostFindAllRequest request;
if (sorts == null) {
request = new PostFindAllRequest(page, size);
}
else {
List<SortOption> options = sorts.stream().map((sort) -> {
String[] keyOption = sort.split(",");
return new SortOption(keyOption[0], keyOption[1]);
}).toList();
request = new PostFindAllRequest(page, size, options);
}
List<PostFindAllResponse> posts = postService.findAll(request);
return ResponseEntity.ok(BaseResponse.success(posts));
}
Service
입력받은 정렬 조건을 Spring Data JPA가 사용하는 Sort의 객체들로 바꾸고, Pageable 인스턴스를 만들면 된다.
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
public List<PostFindAllResponse> findAll(PostFindAllRequest request) {
List<SortOption> sortOptions = request.getSortOptions();
List<Order> orders = sortOptions.stream().map((option) ->
new Order(
Direction.fromOptionalString(option.getOrder())
.orElseThrow(() -> new BaseException(ErrorCode.INVALID_SORT_DIRECTION)),
option.getKey()
)
).toList();
Sort sort = Sort.by(orders);
Pageable pageable = PageRequest.of(request.getPage(), request.getSize(), sort);
Page<Post> posts = postRepository.findAll(pageable);
return posts.stream().map(PostFindAllResponse::new).toList();
}
Repository
Spring Data JPA의 쿼리 메서드에 Pageable을 인자로 넣으면 페이지네이션 쿼리를 생성한다.
public interface PostRepository extends JpaRepository<Post, Long> {
Page<Post> findAll(Pageable pageable);
}
반응형
'Tool > Spring' 카테고리의 다른 글
[Spring] Primary Key가 설정된 객체를 영속화 할 때 발생했던 문제 (0) | 2023.12.28 |
---|---|
[Spring] Spring boot와 redis로 회원가입 이메일 인증기능 만들기 (0) | 2023.12.18 |
[Spring] 커스텀 어노테이션으로 DTO 유효성 검사하기 (0) | 2023.12.14 |
[Spring boot] 외부 파일 저장소를 사용할 때 트랜잭션은 어떻게 관리해야 할까? (with. AWS S3) (2) | 2023.12.11 |
[Spring boot] controller layer 테스트 코드 작성하기 (0) | 2023.12.04 |