인프런 커뮤니티 질문&답변

Tony님의 프로필 이미지

작성한 질문수

실전! 코틀린과 스프링 부트로 도서관리 애플리케이션 개발하기 (Java 프로젝트 리팩토링)

40강. UserLoanHistoryRepository를 Querydsl으로 리팩토링 하기

QueryDSL Pageable 질문

22.09.11 16:57 작성

·

843

0

안녕하세요, 강의 잘 듣고 있습니다.

동적 쿼리 구성을 하려다가

기존에

findByName(name: String, pageable: Pageable)

이라는 함수를 써서 쉽게 sorting 및 pagination 을 구현했는데요.

영상에서처럼 검색 조건이 늘어나서 QueryDSL 로 바꾸려고 하는데, 혹시 pageable 을 쉽게 QueryDSL 에서 구현하는 방법이 있을까요?

답변 2

5

최태현님의 프로필 이미지
최태현
지식공유자

2022. 09. 11. 22:58

안녕하세요~! Tony님!!! ㅎㅎㅎ 아이고~~ 좋은 질문이십니다!!!

우선 간단하게 Pageable 을 바로 사용하기는 어려워 다음과 같이 limit / offset으로 치환해주어야 합니다!

fun findAll(pageable: Pageable): List<Book> {
  return queryFactory.select(book)
    .from(book)
    .limit(pageable.pageSize.toLong())
    .offset(pageable.offset)
    .fetch()
}

 

하지만~~ Kotlin의 Extension function을 활용하면 다음과 같은 유틸성 함수를 만들 수 있고 모든 코드에서 Pageable을 바로 사용하는 것처럼 쓸 수 있습니다!

// 유틸 파일에 모아두기!
fun <T> JPAQuery<T>.withPageable(pageable: Pageable): JPAQuery<T> {
  return this.limit(pageable.pageSize.toLong())
    .offset(pageable.offset)
}

// 이제 다른 모든 Repository에서는 다음과 같이 활용 가능
fun findAll(pageable: Pageable): List<Book> {
  return queryFactory.select(book)
    .from(book)
    .withPageable(pageable)
    .fetch()
}

 

위와 같이 확장함수를 잘 활용하 매우 편리한 개발이 가능하더라고요!! 좋은 질문 감사합니다 ㅎㅎㅎㅎ 또 궁금하신 점 있으시면 편하게 질문 주세요~! 감사합니다! 😊

0

Tony님의 프로필 이미지
Tony
질문자

2022. 09. 14. 18:12

친절한 답변 너무 감사합니다!

제가 찾아보다보니까 이런 방법도 있던데, 혹시 많이 사용하는 방법일까요?

QuerydslRepositorySupport 를 상속해서 querydsl (getQuerydsl()) 을 가지고 applyPagination 을 하면 따로 유틸성 함수 추가 없이 사용이 가능하더라구요..!

 

@Component
class ContentQuerydslRepository<T>(
    private val queryFactory: JPAQueryFactory
) : QuerydslRepositorySupport(Content::class.java) {

    fun findContent(
        title: String?, dtype: String?,
        category: String?, pageable: Pageable
    ): List<Content> {
        val query = queryFactory
            .selectFrom(content)
            .where(
                title?.let { content.title.contains(title) },
                dtype?.let { content.dtype.eq(ContentType(dtype)) },
                category?.let { content.category.eq(ContentCategory(category)) },
            )

        return querydsl!!.applyPagination(pageable, query).fetch()

    }
}
최태현님의 프로필 이미지
최태현
지식공유자

2022. 09. 15. 20:55

저는 개인적으로 많이 사용하지 않습니다! 그 이유는 1) 상속하는 것 자체가 약간 번거롭기도 하고, 2) 도메인 클래스 (Class<?>)를 넣어줘야 하는데 쿼리가 복잡해질 수록 N개의 Entity가 사용되기도 하기 때문이에요!!

유틸성 함수 같은 경우는 한 번만 추가하면 계속 사용할 수 있다보니, 크게 불편함을 느끼지 못하고 있습니다 ㅎㅎㅎㅎㅎ

Tony님의 프로필 이미지
Tony
질문자

2022. 09. 16. 09:52

아 그런 문제가 있을 수 있겠군요. 답변 감사합니다!

Tony님의 프로필 이미지

작성한 질문수

질문하기