Spring/데이터 액세스 계층

[Spring] JDBC 페이지네이션

한비Skyla 2024. 6. 19. 19:55

☘️  Repository

 Page<Member> findAllByOrderByMemberIdDesc (Pageable pageable);
public interface MemberRepository extends PagingAndSortingRepository<Member, Long> {
    Optional<Member> findByEmail(String email);
}

이 방법을 쓸 수도 있지만, PagingAndSortingRepostiry <member, Long>을 씀으로써

findAllByOrderByMemberIdDesc 를 쓰지 않아도 됨. 

 

Spring Data JPA 페이징과 정렬

Repository 인터페이스 작성 시 JpaRepository가 아니라 PagingAndSortingRepository를 상속하게 하면, Spring Data JPA에서 제공하는 페이징, 정렬 기능을 이용할 수 있다. public interface UserRepository extends PagingAndSortin

dev-j.tistory.com

 

☘️ MemberService

 public Page<Member> findMembers(int page, int size) {

        // PageRequest 는 구현체임....!!! 여기에 Page, size 를 넣으면, 이 기준으로 페이지네이션이 동작함.
        // PageRequest pageRequest = PageRequest.of(page, size);
        // pageable 이 상위에 있기 때문에 타입으로 받을 수 있음.
        
        
        // Repository 에 있는 PagingAndSortingRepository 덕분에 .of(page, size,,,,)를 쓸 수 있음. 
        Pageable pageable = PageRequest.of(page, size, Sort.by("memberId").descending());
        // findAll 에 구현된 pageRequest 를 받을 수 있음. 
        return memberRepository.findAll(pageable);
    }

 

☘️ MultiResponseDto

- 광역으로 받아서 모든 도메인에 쓸 수 있도록 함. 

- pageInfo 를 받는 ResposeDto 임. 

//getter 가 없으면, 조회가 안됨. dto 에는 꼭 넣어주어야 함!
@Getter
@NoArgsConstructor
public class MultiResponseDto<T> {
    // 제네릭을 쓰는 이유: 타입을 제한하기 위해서. 타입 매개변수가 지금 list에 쓰임. 
    // 타입매개변수만 써도 반환하는 건 list.
    private List<T> data;
    private PageInfo pageInfo;
    
//    public MultiResponseDto(List<T> data, PageInfo pageInfo) {
//        this.data = data;
//        this.pageInfo = pageInfo;
//    }
    
    // page 로 받는 이유 : pageInfo를 그대로 받기 보다는 , 
                        // 객체를 새로 만들어서 할당하는 것이 확장성에 좋음. 
    public MultiResponseDto(List<T> data, Page page) {
        this.data = data;
        this.pageInfo = new PageInfo(page.getNumber() + 1, page.getSize(),
                page.getTotalElements(), page.getTotalPages());
    }
}

 

☘️ PageInfo

- 광역으로 받아서 모든 도메인에 쓸 수 있도록 함. 

- Dto class @Getter 잊지 앉기!!! 

@Getter
@Setter
@AllArgsConstructor
public class PageInfo {
    private int page;
    private int size;
    private long totalElements;
    private int totalPages;
}

 

☘️ MemberController

// @RequestParam 으로 page 와 size 를 받아야 함을 강제. 
public ResponseEntity getMembers(@Positive @RequestParam int page,
                                     @Positive @RequestParam int size) {
    
        // page 1 페이지를 주세요 ! 하면 controller 에서는 0으로 받아서 관리해야 함.
        // 1번째 페이지가 0번 인덱스 같은 느낌.그래서 page -1
        Page<Member> memberPage = memberService.findMembers(page - 1, size);
        // page 안의 content 만 받고 싶기 때문에 getContent() 를 하는 것. 
        List<Member> members = memberPage.getContent();
        // memberResponseDto 로 변환함. 
        List<MemberResponseDto> response = mapper.membersToMemberResponseDtos(members);
                                      // responseDto로 원하는 응답의 모양으로 나오도록 함. 
        return new ResponseEntity<>(new MultiResponseDto(response, memberPage), HttpStatus.OK);
    }