프론트엔드 쪽에서 회원 목록을 조회하는 API에 대해 한 페이지에 데이터 10개씩 페이징해서 결과를 달라는 요청을 했다. 그래서 처음으로 데이터 페이징 기능 구현한 겸 글을 써본다.
1. Controller
@GetMapping("/admin/members")
public MemberListVO lookUpMembers(@RequestParam(name = "page") int page) {
try {
return adminService.lookUpmembers(page);
} catch (Exception e) {
return MemberListVO.builder()
.resultCode(e.getMessage())
.build();
}
}
이름을 lookuUpmembers으로 했는데 지금 보니까 이름을 좀 잘못 지은 거 같다. totalLookupmembers나 lookupAllMembers라고 했으면 좀 더 알아보기 쉬웠을 거 같다. 짧은 영어 실력이 원망스럽다.
2. Service
/**
* 전체 회원 조회
* @param page
* @return
* @throws Exception
*/
@Override
public MemberListVO lookUpmembers(int page) throws Exception{
try {
Page<Member> members = memberService.findAllMembers(page);
List<MemberListDTO> resultData = new ArrayList<>();
for (Member member : members.getContent()) {
resultData.add(MemberListDTO.builder()
.memberId(member.getMemberId())
.email(member.getEmail())
.memberName(member.getMemberName())
.signupDate(member.getSignUpDate())
.postCount(postService.countPostById(member.getMemberId())) //글 개수
.visitCount(member.getVisitCount())
.privilege(member.convertPrivilege())
.reportNum(punishService.countBytargetId(member.getMemberId())) //신고 수
.authority(member.convertAuthority())
.build());
}
System.out.println("members.getTotalPages() = " + members.getTotalPages());
System.out.println("members.getNumber() = " + members.getNumber());
return MemberListVO.builder()
.resultCode("success")
.resultDataNum(members.getTotalElements())
.resultData(resultData)
.currentPage(members.getNumber())
.totalPage(members.getTotalPages())
.sort(members.getSort())
.build();
} catch (NullPointerException e) {
throw new Exception("failed : 조회할 수 있는 회원이 없습니다.");
}
}
MemberService의 findAllMembers() 메서드를 호출해서 Page 리스트의 형태로 값을 받아왔다. 회원을 조회할 때 예외가 발생하면 에러 메시지를 반환한다. 만약 나쁜 사용자가 page=10000 같은 큰 수를 입력했을 때를 대비했다.
private final int contentsSize = 10;
/**
* 전체 회원 조회(페이징)
* @param page
* @return
* @throws NullPointerException
*/
@Override
public Page<Member> findAllMembers(int page) throws NullPointerException{
PageRequest pageRequest = PageRequest.of(page - 1, contentsSize, Sort.by(Sort.Direction.ASC, "id"));
Page<Member> allMembers = memberRepository.findAllMembers(pageRequest);
if (allMembers.getContent().isEmpty()) {
throw new NullPointerException("조회할 수 있는 회원이 없습니다.");
} else {
return allMembers;
}
}
contentsSize는 상수로 설정해서 언제든 바꿀 수 있게 해뒀다.
3.Repository
//전체 회원 조회
@EntityGraph(attributePaths = {"admin"})
@Query("select m from Member m where m.delete = 0")
Page<Member> findAllMembers(Pageable pageable);
페치 조인을 사용하지 않으면 쿼리 낭비가 있는데 페치 조인을 사용하면 페이징이 되지 않는다. 그래서 @EntityGraph를 사용해봤는데 이건 된다. 이것도 안 되면 배치 사이즈 조절해서 해결하려고 했는데 그럴 필요가 없어졌다.
결과
{
"resultCode": "success",
"resultDataNum": 3,
"resultData": [
{
"memberId": 1,
"email": "hello123@email.com",
"memberName": "신림동 모드리치",
"signupDate": "2023-01-13T09:00:00",
"postCount": 1,
"visitCount": 100,
"privilege": "일반 회원",
"reportNum": 1,
"authority": "인증 완료"
},
{
"memberId": 3,
"email": "hi123@email.com",
"memberName": "대치동 메시",
"signupDate": "2023-01-25T09:00:00",
"postCount": 1,
"visitCount": 0,
"privilege": "일반 회원",
"reportNum": 1,
"authority": "이메일 인증 전"
},
{
"memberId": 4,
"email": "admin@email.com",
"memberName": "관리자1",
"signupDate": "2023-12-13T09:00:00",
"postCount": 1,
"visitCount": 999,
"privilege": "관리자",
"reportNum": 0,
"authority": "인증 완료"
}
],
"currentPage": 0,
"totalPage": 1,
"sort": {
"unsorted": false,
"sorted": true,
"empty": false
}
}
아주 만족스럽게 반환되는 것을 확인할 수 있다.
{
"resultCode": "failed : 조회할 수 있는 회원이 없습니다.",
"resultDataNum": null,
"resultData": null,
"currentPage": 0,
"totalPage": 0,
"sort": null
}
에러가 발생하면 이렇게 나온다.
'개발 > Field-Passer 프로젝트' 카테고리의 다른 글
[Field-Passer 프로젝트] Spring Data JPA에서 NativeQuery로 기간 검색하고 DTO로 값 받기 (1) | 2023.02.05 |
---|---|
[Field-Passer 프로젝트] 쿼리 최적화 (N + 1 문제 해결하기) (0) | 2023.02.04 |
[Field-Passer 프로젝트] SpringBoot 로그인 시 예외 처리하기 (0) | 2023.01.30 |
[Field-Passer 프로젝트] Rest API에서 JSON 반환하기 (1) | 2023.01.29 |
[Field-Passer 프로젝트] JPA 사용해서 Entity 설계하기 (0) | 2023.01.29 |
댓글