설치&설정 관련/Spring Framework

spring jpa 사용시 페이징 처리

lahuman 2024. 8. 1. 18:15
728x90

게시글 목록 기능에서 페이징 처리는 단순하지만 많이 사용되는 기능입니다.

주요 항목

  • 요청 값 : 조회 하려는 페이지 위치, 페이지에서 필요로 하는 게시글 수, 추가로 검색 조건
  • 응답 값 : 게시글 목록, 페이지 네비게이션을 위한 총 게시글 수

구현 방법

이를 일일이 구현 하기 보다 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>
}

참고 자료



728x90