QueryDSL을 이용해서 조회를 하고 데이터를 불러올 때 페이징 처리를 하는 방법에 대해 알아보겠습니다. QueryDSL로 페이징을 처리하는 방법은 의외로 생각 보다 더 간단했습니다. 

 

JPQL Pageable

기존에는 Spring Data JPA에서 제공하는 기능인 Pageable 기능을 사용하여 매우 쉽게 처리 했었는데 아래와 같습니다.

List<Post> findByTitleContainsOrContentsContains(Pageable pageable, String search, String searchContents);

Pageable 을 깊게 들어가면 아래와 같이 나옵니다.

/*
 * Copyright 2008-2022 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.springframework.data.domain;

import java.util.Optional;

import org.springframework.util.Assert;

/**
 * Abstract interface for pagination information.
 *
 * @author Oliver Gierke
 * @author Mark Paluch
 */
public interface Pageable {

   /**
    * Returns a {@link Pageable} instance representing no pagination setup.
    *
    * @return
    */
   static Pageable unpaged() {
      return Unpaged.INSTANCE;
   }

   /**
    * Creates a new {@link Pageable} for the first page (page number {@code 0}) given {@code pageSize} .
    *
    * @param pageSize the size of the page to be returned, must be greater than 0.
    * @return a new {@link Pageable}.
    * @since 2.5
    */
   static Pageable ofSize(int pageSize) {
      return PageRequest.of(0, pageSize);
   }

   /**
    * Returns whether the current {@link Pageable} contains pagination information.
    *
    * @return
    */
   default boolean isPaged() {
      return true;
   }

   /**
    * Returns whether the current {@link Pageable} does not contain pagination information.
    *
    * @return
    */
   default boolean isUnpaged() {
      return !isPaged();
   }

   /**
    * Returns the page to be returned.
    *
    * @return the page to be returned or throws {@link UnsupportedOperationException} if the object is
    *         {@link #isUnpaged()}.
    * @throws UnsupportedOperationException if the object is {@link #isUnpaged()}.
    */
   int getPageNumber();

   /**
    * Returns the number of items to be returned.
    *
    * @return the number of items of that page or throws {@link UnsupportedOperationException} if the object is
    *         {@link #isUnpaged()}.
    * @throws UnsupportedOperationException if the object is {@link #isUnpaged()}.
    */
   int getPageSize();

   /**
    * Returns the offset to be taken according to the underlying page and page size.
    *
    * @return the offset to be taken or throws {@link UnsupportedOperationException} if the object is
    *         {@link #isUnpaged()}.
    * @throws UnsupportedOperationException if the object is {@link #isUnpaged()}.
    */
   long getOffset();

   /**
    * Returns the sorting parameters.
    *
    * @return
    */
   Sort getSort();

   /**
    * Returns the current {@link Sort} or the given one if the current one is unsorted.
    *
    * @param sort must not be {@literal null}.
    * @return
    */
   default Sort getSortOr(Sort sort) {

      Assert.notNull(sort, "Fallback Sort must not be null");

      return getSort().isSorted() ? getSort() : sort;
   }

   /**
    * Returns the {@link Pageable} requesting the next {@link Page}.
    *
    * @return
    */
   Pageable next();

   /**
    * Returns the previous {@link Pageable} or the first {@link Pageable} if the current one already is the first one.
    *
    * @return
    */
   Pageable previousOrFirst();

   /**
    * Returns the {@link Pageable} requesting the first page.
    *
    * @return
    */
   Pageable first();

   /**
    * Creates a new {@link Pageable} with {@code pageNumber} applied.
    *
    * @param pageNumber
    * @return a new {@link PageRequest} or throws {@link UnsupportedOperationException} if the object is
    *         {@link #isUnpaged()} and the {@code pageNumber} is not zero.
    * @since 2.5
    * @throws UnsupportedOperationException if the object is {@link #isUnpaged()}.
    */
   Pageable withPage(int pageNumber);

   /**
    * Returns whether there's a previous {@link Pageable} we can access from the current one. Will return
    * {@literal false} in case the current {@link Pageable} already refers to the first page.
    *
    * @return
    */
   boolean hasPrevious();

   /**
    * Returns an {@link Optional} so that it can easily be mapped on.
    *
    * @return
    */
   default Optional<Pageable> toOptional() {
      return isUnpaged() ? Optional.empty() : Optional.of(this);
   }

}

 

 

 

 

 

 

QueryDSL 페이징 처리 하기

 

@Override

    public List<Post> findByTitleContainsOrContentsContains(Pageable pageable, String search, String searchContents) {

        return jpaQueryFactory.selectFrom(post)

                .where(post.title.contains(search).or(post.title.contains(searchContents)))

                .offset(pageable.getOffset())

                .limit(pageable.getPageSize())

                .fetch();

    }

 

offset 과 limit으로 페이징 처리를 합니다.

 

 

 

정작 프로젝트는....

복잡한 쿼리(삭제, 업데이트)에만 QueryDSL을 사용하기로 했으므로 QueryDSL을 사용한 페이징 처리는 하지 않았습니다.

 

 

 

 

TIL QueryDSL 마스터가 되다 (조회, 수정, 삭제, Optional) 230208

QueryDSL 마스터가 되었습니다. 설치하는 과정은 지난 포스팅을 참조해주세요. TIL QueryDSL 5.0.0 적용하기 230206 QueryDSL의 최신 버전(2021.07.22 release)인 5.0 버전을 사용했습니다. 블로그 자료들에는 outdat

pizzathedeveloper.tistory.com

 

 

TIL QueryDSL 5.0.0 적용하기 230206

QueryDSL의 최신 버전(2021.07.22 release)인 5.0 버전을 사용했습니다. 블로그 자료들에는 outdated된 것들이 많아서 최대한 공식 문서와 github을 참조하려고 했습니다. QueryDSL의 github에는 데이터 타입 별

pizzathedeveloper.tistory.com

 

 

 

 

+ Recent posts