본문 바로가기


JPA

[JPA] JPAQuery 에서 Pageable(offset,limit,orderby) 사용하기

org.springframework.data.domain.Pageable

를 입력받고 메소드 쿼리에 사용중이었는데 custom 쿼리를 사용할일이 생겨서 queryDSL 로 새로 구현했다.

Spring data jpa 의 메소드 쿼리에는 Pageable 을 넘겨주면 알아서 처리를 해주는데 queryDSL 에서는 따로 설정해야 했다.

limit, offset 은 비교적 단순했으나 orderBy 에서 추가 구현이 필요해서 이부분을 기록해 두기로 한다.

 

코드를 첨부한다.

@Repository
class XXCustomRepositoryImpl(
    @Qualifier("xxQueryFactory")
    private val xxQueryFactory: JPAQueryFactory,
) : XXQuerydslRepositorySupport(XXEntity::class.java), XXCustomRepository {
    override fun findAllByCriteria(pageable: Pageable): Page<XXEntity> {
        val results =
            xxQueryFactory.selectFrom(xxEntity)
                .distinct()
            .where(
                ...
            )
            .offset(pageable.offset)
            .orderBy(sort(pageable))
            .limit(pageable.pageSize.toLong())
            .fetch()

        val countQuery = xxQueryFactory
            .selectFrom(xxEntity)
            .where(
                ...
            )

        return PageableExecutionUtils.getPage(results, pageable) { countQuery.fetch().size.toLong() }
    }

    private fun sort(page: Pageable): OrderSpecifier<*>? {
        if (!page.sort.isEmpty) {
            for (order in page.sort) {
                val direction = if (order.direction.isAscending) Order.ASC else Order.DESC
                when (order.property) {
                    "createdAt" -> return OrderSpecifier(direction, xxEntity.createdAt)
                    "updatedAt" -> return OrderSpecifier(direction, xxEntity.updatedAt)
                    "id" -> return OrderSpecifier(direction, xxEntity.id)
                }
            }
        }
        return null
    }
}​

어떤걸 사용하느냐에 따라 조금 다른데 JPAQuery 를 사용 하면 order 에 OrderSpecifier 를 사용 해야 해서 위 코드처럼 구현할 수 있다.

도메인코드를 XX 로 치환하는 과정이랑 where 절에서 컴파일에러가 날텐데 이건 알아서 해결해주세요

사실 queryDSL 를 활용한 repository 구현해는 다양한 방법이 있으니 이런 방법도 있다라는 것만 알면 될 것 같다.

 

더 우아하게 짤 수 있는 방법이 있으면 댓글에 알려주시면 좋을 것 같습니다.

 

 

 

끝!