inflearn logo
강의

Course

Instructor

Real-world! Developing a library management application with Kotlin and Spring Boot (Refactoring a Java project)

Lesson 40. Refactoring UserLoanHistoryRepository to Querydsl

QueryDSL Pageable 질문

1028

Tony

8 asked

0

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

동적 쿼리 구성을 하려다가

기존에

findByName(name: String, pageable: Pageable)

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

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

spring kotlin spring-boot java refactoring

Answer 2

5

lannstark

안녕하세요~! 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

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

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

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()

    }
}

1

lannstark

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

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

0

Tony

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

안녕하세요 혹시 프론트 코드 제공받을 수 있을까요?

0

68

2

실행이 안되네요

0

66

2

프론트 영역 보는법

0

51

2

companion object

0

78

2

Custom 레프직토리 형식

0

57

2

Querydsl 도입

0

67

2

fetch join DISTINCT 중복제거

1

83

2

표준 예외와 커스텀 예외 사용 전략 질문

0

86

3

이 질문이 왜 없는지 이해가 안 되지만 문제 인식 및 해결 방법 남깁니다.

1

177

2

테스트를 위한 코드

1

105

2

프로젝트 실행 에러

0

151

2

PDF 문서에 오타가 있어서 알려드립니다.

1

102

1

enum질문

1

86

1

테스트 후 AfterEach 함수에서 나오는 쿼리

0

136

2

테스트 fixture

1

210

2

./gradlew test 실행시 인식할수 없다고 뜹니다.

0

140

1

test 코드 실행시 경고가 발생합니다.

0

140

1

13강 User Kotlin 변환중

2

169

3

'추가 - 코프링과 플러그인' 강의 7:46 allopen 관련 질문

2

174

1

-

0

141

2

4:28 build.gradle 수정 시 kotlin-reflect관련 implementation 추가 해야할까요?

0

312

3

junit import 불가

0

271

3

테스트 코드와 관련하여 질문이 있습니다.

1

218

1

hibernate가 select를 두번 하는 이유

0

240

1