[Kotlin] Paging query needs to have a Pageable parameter 문제 해결
ㅁ 들어가며
Reason: Paging query needs to have a Pageable parameter;
Offending method: public abstract org.springframework.data.domain.Page
ㅇ Spring Data JPA를 사용하여 페이징 쿼리를 실행할 때 발생하는 오류 메시지이다.
ㅇ"Paging query needs to have a Pageable parameter"는 페이징 기능을 사용하려면 Pageable 파라미터가 필요하다는 의미이다.
ㅇ 이 문제를 해결하기 위해서는 리포지토리 메서드에 Pageable 파라미터를 추가해야 한다.
ㅇ 페이징 처리는 [Kotlin] Spring Boot와 Kotlin으로 QueryDSL 페이징 처리하기
ㅁ Import 확인
import org.springframework.data.domain.Pageable; ( ㅇ )
import java.awt.print.Pageable; ( X )
ㅇ 동일명의 다른 객체를 Import를 한 경우 에러가 발생한다.
ㅁ Repository 인터페이스 수정
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
interface EntityNameRepository : JpaRepository<EntityName, Long> {
fun findBySomeField(someField: String, pageable: Pageable): Page<EntityName>
}
ㅇ 페이징 기능을 사용하고자 하는 리포지토리 메서드에 Pageable 파라미터를 추가해야 한다.
ㅇ 예를 들어, 엔티티 EntityName에 대한 리포지토리가 있다고 가정할 때, Pabeable을 추가하면 된다.
ㅁ 커스텀 Repository에 abstract 확인
import com.querydsl.jpa.impl.JPAQueryFactory
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Repository
@Repository
abstract class EntityNameRepositoryImpl( // abstract를 제거 해야 한다.
private val jpaQueryFactory: JPAQueryFactory
): EntityNameRepositoryCustom {
override fun findBySomeField(someField: String, pageable: Pageable): Page<EntityName> {
// TODO paging
}
}
ㅇ 추상 클래스인 경우 객체 자체를 인스턴스화 하지 못하여 pageable을 참조하지 못하는 경우가 있다.
ㅇ runtime 시 추상화 오류가 아닌 pagable 오류만 나타나 추상화로 인한 문제점을 인식하지 못할 수 있다.
ㅇ 나의 경우는 이 상황이어서 원인을 해결하는데 상당 시간이 필요했다.
ㅁ 서비스 레이어에서 Pageable 사용
import org.springframework.data.domain.PageRequest
import org.springframework.stereotype.Service
@Service
class EntityNameService(private val entityNameRepository: EntityNameRepository) {
fun getEntitiesBySomeField(someField: String, page: Int, size: Int): Page<EntityName> {
val pageable = PageRequest.of(page, size)
return entityNameRepository.findBySomeField(someField, pageable)
}
}
ㅇ 서비스 레이어에서 리포지토리 메서드를 호출할 때 Pageable 객체를 생성하여 전달한다.
ㅁ 컨트롤러에서 Pageable 파라미터 받기
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
@RestController
class EntityNameController(private val entityNameService: EntityNameService) {
@GetMapping("/entities")
fun getEntities(
@RequestParam someField: String,
@RequestParam page: Int,
@RequestParam size: Int
): Page<EntityName> {
return entityNameService.getEntitiesBySomeField(someField, page, size)
}
// Pageable 직접 받는 방법
@GetMapping("/entities")
fun getYourEntities(pageable: Pageable): Page<YourEntity> {
return yourEntityService.getYourEntities(pageable)
}
}
ㅇ 컨트롤러에서 클라이언트로부터 페이지 번호와 크기를 받아 서비스 레이어에 전달한다.
ㅇ 컨트롤러에서 Pageable 객체를 직접 받을 수도 있다.
ㅇ Spring MVC는 자동으로 Pageable 객체를 생성해준다.
ㅁ 함께 보면 좋은 사이트
ㅇ JPA Repository에서 Paging query needs to have a Pageable parameter 에러 발생 해결