Framework/Springboot

[Springboot] JPA์™€ pageable ํ™œ์šฉํ•œ sort ์ •๋ ฌ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

yuri lee 2024. 11. 28. 21:19
๋ฐ˜์‘ํ˜•

Intro

์•ˆ๋…•ํ•˜์„ธ์š”. ์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” spring boot ์—์„œ JPA์™€ pageable ํ™œ์šฉํ•œ sort ์ •๋ ฌ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. user ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฐ€์ •ํ•˜์— ์ง„ํ–‰ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

1. User ์—”ํ‹ฐํ‹ฐ ์ •์˜ 

User ์—”ํ‹ฐํ‹ฐ์—๋Š” id, name, email, createdDate ๋“ฑ์˜ ํ•„๋“œ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

@Entity
data class User(
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long,

    val name: String,
    val email: String,

    @CreatedDate
    val createdDate: LocalDateTime
)

 

2. UserRepository ์ธํ„ฐํŽ˜์ด์Šค ์ •์˜

User ๋ฐ์ดํ„ฐ๋ฅผ ํŽ˜์ด์ง•๊ณผ ์ •๋ ฌ๋กœ ์กฐํšŒํ•˜๊ธฐ ์œ„ํ•ด JpaRepository๋ฅผ ์ƒ์†ํ•œ UserRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. JpaRepository๋Š” ํŽ˜์ด์ง•๊ณผ ์ •๋ ฌ์„ ์ž๋™์œผ๋กœ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. findAll(Pageable pageable) ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํŽ˜์ด์ง• ๋ฐ ์ •๋ ฌ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‰ฝ๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface UserRepository : JpaRepository<User, Long>

 

3. UserController์—์„œ Pageable๊ณผ Sort ์‚ฌ์šฉ

3.1. ๊ธฐ๋ณธ์ ์ธ ํŽ˜์ด์ง•๊ณผ ์ •๋ ฌ

Pageable ๊ฐ์ฒด๋Š” URL ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ page, size, sort๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„ ์ฝ”๋“œ์—์„œ๋Š” pageable ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ findAll(pageable)์„ ํ˜ธ์ถœํ•˜๊ณ , Spring Data JPA๊ฐ€ ์ œ๊ณตํ•˜๋Š” ํŽ˜์ด์ง•๊ณผ ์ •๋ ฌ ๊ธฐ๋Šฅ์„ ์ž๋™์œผ๋กœ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

@RestController
@RequestMapping("/users")
class UserController(private val userRepository: UserRepository) {

    @GetMapping
    fun getUsers(
        pageable: Pageable // Spring Data JPA๊ฐ€ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” Pageable ๊ฐ์ฒด
    ): ResponseEntity<Page<User>> {
        val users = userRepository.findAll(pageable) // pageable์„ ์‚ฌ์šฉํ•˜์—ฌ ํŽ˜์ด์ง•๊ณผ ์ •๋ ฌ ์ ์šฉ
        return ResponseEntity.ok(users)
    }
}

 

3.2. URL ์˜ˆ์‹œ

๋‹ค์Œ๊ณผ ๊ฐ™์€ URL๋กœ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Spring Boot๋Š” ์ž๋™์œผ๋กœ Pageable ๊ฐ์ฒด๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  findAll(pageable)์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ, name ํ•„๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ๋œ User ๋ฐ์ดํ„ฐ๋ฅผ ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€์—์„œ 10๊ฐœ์”ฉ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

GET /users?page=0&size=10&sort=name,asc
  • page=0: ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€ (0๋ถ€ํ„ฐ ์‹œ์ž‘) 
  • size=10: ํ•œ ํŽ˜์ด์ง€์— 10๊ฐœ์˜ ๋ฐ์ดํ„ฐ 
  • sort=name,asc: name ํ•„๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ

 

3.3. ์—ฌ๋Ÿฌ ํ•„๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•˜๊ธฐ

์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ•„๋“œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌํ•˜๋ ค๋ฉด sort ํŒŒ๋ผ๋ฏธํ„ฐ์— ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋œ ์ •๋ ฌ ๊ธฐ์ค€์„ ์ „๋‹ฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, name ํ•„๋“œ๋ฅผ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ, createdDate ํ•„๋“œ๋ฅผ ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๋ ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด URL์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GET /users?page=0&size=10&sort=name,asc,createdDate,desc

 

3.4. PageRequest์™€ Sort๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง์ ‘ ์„ค์ •

ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ •๋ ฌ ๊ธฐ์ค€์„ ๋ณด๋‚ด์ง€ ์•Š๊ณ , ์„œ๋ฒ„์—์„œ ์ง์ ‘ PageRequest์™€ Sort๋ฅผ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

@GetMapping("/users/custom-sort")
fun getUsersWithCustomSort(): ResponseEntity<Page<User>> {
    // ๊ธฐ๋ณธ์ ์œผ๋กœ name์„ ์˜ค๋ฆ„์ฐจ์ˆœ, createdDate๋ฅผ ๋‚ด๋ฆผ์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌ
    val sort = Sort.by(Sort.Order.asc("name"), Sort.Order.desc("createdDate"))
    val pageable = PageRequest.of(0, 10, sort) // ์ฒซ ํŽ˜์ด์ง€, 10๊ฐœ์”ฉ, ์ •๋ ฌ ๊ธฐ์ค€ ์„ค์ •
    val users = userRepository.findAll(pageable)
    return ResponseEntity.ok(users)
}
๋ฐ˜์‘ํ˜•