해결된 질문
작성
·
639
·
수정됨
0
[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (아니오)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)
[질문 내용]
지금 질문은 querydsl 뿐만 아니라 spring data jpa도 섞여있습니다.
여태 Spring Data JPA로 페이징을 처리할 때는
Page<BoardEntity> findAllByItemItemId(Long itemId, Pageable pageable);
@Query(value = "select b from board b " +
" join fetch b.member " +
" join fetch b.item " +
"where b.item.itemId = :itemId" +
" order by b.boardId desc ",
countQuery = "select count(b) from board b where b.item.itemId = :itemId")
Page<BoardEntity> findAllByItemItemId(@Param("itemId") Long itemId, Pageable pageable);
이렇게 처리하고
서비스에서
// 상품에 대한 문의글 보기
@Transactional(readOnly = true)
@Override
public Page<BoardDTO> getBoards(Pageable pageable,
Long itemId,
String email) {
// 회원 조회
MemberEntity findUser = memberRepository.findByEmail(email);
log.info("유저 : " + findUser);
// 상품 조회
ItemEntity findItem = itemRepository.findById(itemId)
.orElseThrow(EntityNotFoundException::new);
log.info("상품 : " + findItem);
// 조회해올 게시글을 넣을 곳
Page<BoardEntity> findAllBoards = boardRepository.findAllByItemItemId(itemId, pageable);
// 댓글이 있으면 답변완료, 없으면 미완료
for(BoardEntity boardCheck : findAllBoards) {
if(boardCheck.getCommentEntityList().isEmpty()) {
boardCheck.changeReply(ReplyStatus.REPLY_X);
} else {
boardCheck.changeReply(ReplyStatus.REPLY_O);
}
}
for (BoardEntity boardEntity : findAllBoards) {
// 파라미터로 받아온 이메일이 있다면
if (email != null) {
// 해당 게시글을 만들때 이메일과 조회한 이메일을 체크
// 그리고 맞다면 읽을 권한주고 없으면 잠가주기
if (boardEntity.getMember().getEmail().equals(findUser.getEmail())) {
boardEntity.changeSecret(BoardSecret.UN_LOCK);
} else {
boardEntity.changeSecret(BoardSecret.LOCK);
}
} else {
boardEntity.changeSecret(BoardSecret.LOCK);
}
}
log.info("조회된 게시글 수 : {}", findAllBoards.getTotalElements());
log.info("조회된 게시글 : {}", findAllBoards);
return findAllBoards.map(board -> BoardDTO.toBoardDTO(
board,
board.getMember().getNickName(),
board.getItem().getItemId()));
}
// 상품에 대한 문의글 전체 보기
@GetMapping("")
@Tag(name = "board")
@Operation(summary = "문의글 전체 보기", description = "모든 상품에 대한 문의글을 봅니다.")
public ResponseEntity<?> getBoards(
// SecuritConfig에 Page 설정을 한 페이지에 10개 보여주도록
// 설정을 해서 여기서는 할 필요가 없다.
@PageableDefault(sort = "boardId", direction = Sort.Direction.DESC)
Pageable pageable,
@PathVariable(name = "itemId") Long itemId,
@RequestParam(value = "email", required = false) String email) {
try {
log.info("email : " + email);
// 검색하지 않을 때는 모든 글을 보여준다.
Page<BoardDTO> boards = boardService.getBoards(pageable, itemId, email);
Map<String, Object> response = new HashMap<>();
// 현재 페이지의 아이템 목록
response.put("items", boards.getContent());
// 현재 페이지 번호
response.put("nowPageNumber", boards.getNumber()+1);
// 전체 페이지 수
response.put("totalPage", boards.getTotalPages());
// 한 페이지에 출력되는 데이터 개수
response.put("pageSize", boards.getSize());
// 다음 페이지 존재 여부
response.put("hasNextPage", boards.hasNext());
// 이전 페이지 존재 여부
response.put("hasPreviousPage", boards.hasPrevious());
// 첫 번째 페이지 여부
response.put("isFirstPage", boards.isFirst());
// 마지막 페이지 여부
response.put("isLastPage", boards.isLast());
return ResponseEntity.ok().body(response);
} catch (Exception e) {
return ResponseEntity.badRequest().build();
}
}
이렇게 처리를 했습니다. Page 기능을 사용해서 구현했고 querydsl에서 페이징처리는 다음과 같이 했습니다.
@Override
public Page<MemberTeamDTO> searchPageComplex(MemberSearchCondition condition,
Pageable pageable) {
List<MemberTeamDTO> content = queryFactory
.select(new QMemberTeamDTO(
member.id.as("memberId"),
member.userName,
member.age,
team.id.as("teamId"),
team.name.as("teamName")))
.from(member)
.leftJoin(member.team, team)
.where(userNameEq(condition.getUserName()),
teamNameEq(condition.getTeamName()),
ageGoe(condition.getAgeGoe()),
ageLoe(condition.getAgeLoe()))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
// count 쿼리 (조건에 부합하는 로우의 총 개수를 얻는 것이기 때문에 페이징 미적용)
long total = queryFactory
// SQL 상으로는 count(member.id)와 동일
.select(member.count())
.from(member)
// .leftJoin(member.team, team)
.where(userNameEq(condition.getUserName()),
teamNameEq(condition.getTeamName()),
ageGoe(condition.getAgeGoe()),
ageLoe(condition.getAgeLoe()))
.fetchOne();
return new PageImpl<>(content, pageable, total);
}
fetchResult와 fetchCount가 지원을 안한다고 해서 조건에 따라 카운트를 구해서 총 개수를 구해서 하는 방식으로 했는데 이렇게 했을 때도
Map<String, Object> response = new HashMap<>();
// 현재 페이지의 아이템 목록
response.put("items", boards.getContent());
// 현재 페이지 번호
response.put("nowPageNumber", boards.getNumber()+1);
// 전체 페이지 수
response.put("totalPage", boards.getTotalPages());
// 한 페이지에 출력되는 데이터 개수
response.put("pageSize", boards.getSize());
// 다음 페이지 존재 여부
response.put("hasNextPage", boards.hasNext());
// 이전 페이지 존재 여부
response.put("hasPreviousPage", boards.hasPrevious());
// 첫 번째 페이지 여부
response.put("isFirstPage", boards.isFirst());
// 마지막 페이지 여부
response.put("isLastPage", boards.isLast());
이런식으로 뽑아서 프론트에 보낼 수 있는지와
실무에서도 spring data jpa와 querydsl 방식으로 페이징 처리를 할 때 이렇게 하는지 아니면 다른 방식이 더있는지 궁금해서 질문드립니다.
답변 2
0
안녕하세요, 인프런 AI 인턴입니다.
페이징 처리에 대한 궁금증을 해결하기 위한 유사한 질문과 답변이 있어 링크를 안내해 드릴게요.
spqkwh159님의 질문: “searchSimple 에 관한 질문입니다.“에 대한 답변 링크입니다. 페이지네이션 처리와 관련된 문제 해결에 대한 팁을 얻을 수 있을 거예요.
searchSimple 에 관한 질문입니다.
crispin님의 질문: “페이징 했을때 발생하는 문제”에 대한 답변 링크입니다. 페이징 처리 시 countQuery를 별도로 작성해야 하는 상황에 대한 설명이 담겨 있습니다.
페이징 했을때 발생하는 문제
위 링크들을 참조하시어 페이징 처리에 대한 이해를 높이시고, 실무에서의 적용 방법에 대한 힌트를 얻으실 수 있기를 바랍니다.