Skip to content

Commit

Permalink
feat: 기록 페이징 조회 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
sunghyuki committed May 22, 2024
1 parent c1d64e4 commit e023baa
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import com.climingo.climingoApi.record.api.request.RecordCreateRequest;
import com.climingo.climingoApi.record.api.request.RecordUpdateRequest;
import com.climingo.climingoApi.record.api.response.PageDto;
import com.climingo.climingoApi.record.api.response.RecordResponse;
import com.climingo.climingoApi.record.application.RecordService;
import com.climingo.climingoApi.record.domain.Record;
import jakarta.validation.constraints.Min;
import java.io.IOException;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand All @@ -26,7 +28,7 @@ public class RecordController {

@PostMapping("/records")
public ResponseEntity<Long> create(@ModelAttribute RecordCreateRequest request)
throws IOException, InterruptedException {
throws IOException, InterruptedException {
Record record = recordService.createRecord(request);
return ResponseEntity.ok().body(record.getId());
}
Expand All @@ -51,9 +53,22 @@ public ResponseEntity<RecordResponse> find(@PathVariable("recordId") Long record

@GetMapping("/records")
public ResponseEntity<List<RecordResponse>> findAll(@RequestParam(value = "gymId", required = false) Long gymId,
@RequestParam(value = "levelId", required = false) Long levelId, @RequestParam(value = "memberId", required = false) Long memberId) {
@RequestParam(value = "levelId", required = false) Long levelId,
@RequestParam(value = "memberId", required = false) Long memberId) {
List<RecordResponse> recordResponses = recordService.findAll(gymId, levelId, memberId);
return ResponseEntity.ok().body(recordResponses);
}

@GetMapping("/records/paged")
public ResponseEntity<PageDto<RecordResponse>> findPage(@RequestParam(value = "gymId", required = false) Long gymId,
@RequestParam(value = "levelId", required = false) Long levelId,
@RequestParam(value = "memberId", required = false) Long memberId,
@RequestParam(value = "page", required = false, defaultValue = "0") @Min(0) Integer page,
@RequestParam(value = "size", required = false, defaultValue = "10") @Min(1) Integer size) {

PageDto<RecordResponse> pageDto = recordService.findPage(gymId, levelId, memberId, page, size);// TODO: 예외 global 하게 처리 필요

return ResponseEntity.ok().body(pageDto);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.climingo.climingoApi.record.api.response;

import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public class PageDto<T> {

private Long totalCount;

private Integer resultCount;

private Boolean isEnd;

private List<T> contents;

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.climingo.climingoApi.gym.domain.Gym;
import com.climingo.climingoApi.member.domain.Member;
import com.climingo.climingoApi.record.domain.Record;
import lombok.Builder;
import lombok.Getter;

@Getter
Expand All @@ -17,6 +18,7 @@ public class RecordResponse {

private ShortLevelResponse level;

@Builder
public RecordResponse(Member member, Record record, Gym gym,
Level level) {
this.memberInfo = new ShortMemberResponse(member.getId(), member.getProfileUrl(), member.getNickname());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.climingo.climingoApi.record.api.response;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
package com.climingo.climingoApi.record.application;

import com.climingo.climingoApi.level.domain.Level;
import com.climingo.climingoApi.level.domain.LevelRepository;
import com.climingo.climingoApi.gym.domain.Gym;
import com.climingo.climingoApi.gym.domain.GymRepository;
import com.climingo.climingoApi.level.domain.Level;
import com.climingo.climingoApi.level.domain.LevelRepository;
import com.climingo.climingoApi.member.domain.Member;
import com.climingo.climingoApi.member.domain.MemberRepository;
import com.climingo.climingoApi.record.api.request.RecordCreateRequest;
import com.climingo.climingoApi.record.api.request.RecordUpdateRequest;
import com.climingo.climingoApi.record.api.response.PageDto;
import com.climingo.climingoApi.record.api.response.RecordResponse;
import com.climingo.climingoApi.record.domain.Record;
import com.climingo.climingoApi.record.domain.RecordRepository;
import com.climingo.climingoApi.upload.S3Service;
import com.climingo.climingoApi.upload.ThumbnailExtractor;
import jakarta.persistence.EntityNotFoundException;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -46,13 +48,13 @@ public Record createRecord(RecordCreateRequest request) throws IOException {
String thumbnailImageUrl = s3Service.uploadImageFile(thumbnailExtractor.extractImage(videoUrl));

Record record = Record.builder()
.member(mockMember())
.gym(gym)
.level(level)
.content(null)
.videoUrl(videoUrl)
.thumbnailUrl(thumbnailImageUrl)
.build();
.member(mockMember())
.gym(gym)
.level(level)
.content(null)
.videoUrl(videoUrl)
.thumbnailUrl(thumbnailImageUrl)
.build();

Record save = recordRepository.save(record);
return save;
Expand Down Expand Up @@ -103,6 +105,24 @@ public List<RecordResponse> findAll(Long gymId, Long levelId, Long memberId) {
return recordResponses;
}

@Transactional(readOnly = true)
public PageDto<RecordResponse> findPage(Long gymId, Long levelId, Long memberId, Integer page, Integer size) {
Page<Record> recordPage = recordRepository.findRecordPage(gymId, levelId, memberId, page, size);

return PageDto.<RecordResponse>builder()
.totalCount(recordPage.getTotalElements())
.resultCount(recordPage.getNumberOfElements())
.isEnd(recordPage.isLast())
.contents(toRecordResponses(recordPage.getContent()))
.build();
}

private List<RecordResponse> toRecordResponses(List<Record> records) {
return records.stream()
.map(record -> new RecordResponse(record.getMember(), record, record.getGym(), record.getLevel()))
.collect(Collectors.toList());
}

private Member mockMember() {
return memberRepository.findById(9999L).orElseThrow(() -> new EntityNotFoundException(9999L + "is not found"));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.climingo.climingoApi.record.domain;

import java.util.List;
import org.springframework.data.domain.Page;

public interface RecordRepositoryCustom {

List<Record> findAllWithDetails(Long gymId, Long levelId, Long memberId);

Page<Record> findRecordPage(Long gymId, Long levelId, Long memberId, Integer page, Integer size);

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package com.climingo.climingoApi.record.domain;

import static com.climingo.climingoApi.gym.domain.QGym.gym;
import static com.climingo.climingoApi.member.domain.QMember.member;
import static com.climingo.climingoApi.record.domain.QRecord.record;

import com.climingo.climingoApi.gym.domain.QGym;
import com.querydsl.core.types.Order;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;

@RequiredArgsConstructor
public class RecordRepositoryCustomImpl implements RecordRepositoryCustom {
Expand All @@ -22,13 +29,37 @@ public List<Record> findAllWithDetails(Long gymId, Long levelId, Long memberId)
return queryFactory.select(record)
.from(record)
.innerJoin(record.member, member).fetchJoin()
.innerJoin(record.gym, QGym.gym).fetchJoin()
.innerJoin(record.gym, gym).fetchJoin()
.where(gymIdEq(gymId),
levelIdEq(levelId),
memberIdEq(memberId))
.fetch();
}

@Override
public Page<Record> findRecordPage(Long gymId, Long levelId, Long memberId, Integer page, Integer size) {
List<Record> contents = queryFactory.selectFrom(record)
.distinct()
.innerJoin(record.member, member).fetchJoin()
.innerJoin(record.gym, gym).fetchJoin()
.where(gymIdEq(gymId),
levelIdEq(levelId),
memberIdEq(memberId))
.orderBy(new OrderSpecifier<>(Order.DESC, record.createdDate))
.offset((long) page * size)
.limit(size)
.fetch();

JPAQuery<Long> countQuery = queryFactory.select(record.count())
.from(record)
.where(gymIdEq(gymId),
levelIdEq(levelId),
memberIdEq(memberId));

Pageable pageable = PageRequest.of(page, size);
return PageableExecutionUtils.getPage(contents, pageable, countQuery::fetchOne);
}

private BooleanExpression memberIdEq(Long memberId) {
return memberId == null ? null : record.member.id.eq(memberId);
}
Expand Down
Loading

0 comments on commit e023baa

Please sign in to comment.