spring jpa 사용시 페이징 처리
게시글 목록 기능에서 페이징 처리는 단순하지만 많이 사용되는 기능입니다.
주요 항목
- 요청 값 : 조회 하려는
페이지 위치
, 페이지에서 필요로 하는게시글 수
, 추가로검색 조건
- 응답 값 :
게시글 목록
, 페이지 네비게이션을 위한 총게시글 수
구현 방법
이를 일일이 구현 하기 보다 jpa에서 지원하는 Pageable 와 Page 라이브러리를 사용하면 간단한게 처리 됩니다.
예제 코드
// Controller
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
@RestController
class Controller(private val service: ContentsService) {
@GetMapping("/list")
fun getList(
@PageableDefault(page = 0, size = 10) pageable: Pageable
): Page<TipContents> {
return contentsService.getList(pageable)
}
}
// Service
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
@Service
class ContentsService(private val repository: ContentsRepository) {
fun getTipContents(pageable: Pageable): Page<Contents> {
return repository.findAll(pageable)
}
}
// Repository
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
interface TipContentsRepository : JpaRepository<Contents, Long> {
fun findAll(
pageable: Pageable
): Page<Contents>
}
@Query 사용 예제 추가
필요시 사용자 정의 SQL을 사용할 경우 다음과 같이 @Query
를 활용하여도 동일하게 페이징 처리가 됩니다.
// Repository
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
interface TipContentsRepository : JpaRepository<Contents, Long> {
@Query(
"""
SELECT
C.ID,
C.TIP_TITLE,
C.IMG_FILE_PATH ,
C.PET_DCD,
C.OPN_DT ,
C.REG_DTM ,
C.MOD_DTM
'' as TIP_TXT // entity의 필수 값은 무조건 있어야 오류가 발생하지 않습니다.
FROM CONTENTS C
WHERE (C.PET_DCD != :notPetDcd OR C.PET_DCD = 'ALL')
AND C.id IN (
SELECT t.CONTENTS_M_ID
FROM CATEGORY t
WHERE t.CTGY_CCD IN (:ctgyCcds)
)
AND OPN_DT <= TO_CHAR(sysdate, 'YYYYMMDD')
ORDER BY OPN_DT DESC
""",
countQuery = """
SELECT
COUNT(C.ID)
FROM CONTENTS TCM
WHERE (C.PET_DCD != :notPetDcd OR C.PET_DCD = 'ALL')
AND TCM.id IN (
SELECT tcd.CONTENTS_M_ID
FROM CATEGORY t
WHERE t.CTGY_CCD IN (:ctgyCcds)
)
AND OPN_DT <= TO_CHAR(sysdate, 'YYYYMMDD')
""",
nativeQuery = true
)
fun findByPetDcdAndCtgyCcds(
@Param("notPetDcd") notPetDcd: String,
@Param("ctgyCcds") ctgyCcds: List<String>,
pageable: Pageable
): Page<TipContentsM>
}