Published on

「Spring Boot API 開發:從 0 到 1」Day 23 JPA 實現分頁與動態排序

在處理大量資料時,分頁排序是兩個非常重要的功能,它們不僅可以提高應用程式的性能,還能為用戶提供更好的體驗

而 Spring Data JPA 為我們提供了簡單而強大的方法來實現這些功能

今天,我們將深入探討如何在我們的 Todo 應用中實現分頁和動態排序的功能

分頁

修改 Repository

讓我們在 TodoRepository 中增加一個分頁的方法

這個新方法 findAll 接受一個 Pageable 物件,返回一個 Page<Todo> 物件

這裡,我們使用了 Spring Data JPA 提供的 Pageable。它允許我們指定頁碼、每頁大小以及排序信息

// 為了方便,在這裡只展示了所增加的相關程式碼

public interface TodoRepository extends JpaRepository<Todo, Long> {
    Page<Todo> findAll(Pageable pageable);
}

修改 Controller

現在,讓我們在 TodoController 中增加一個使用分頁的方法 (endpoint)  /api/todos/paged

@RestController
@RequestMapping("/api/todos")
public class TodoController {

    // 為了方便,在這裡只展示了所增加的相關程式碼

    @GetMapping("/paged")
    public ResponseEntity<MyApiResponse<Page<Todo>>> getPagedTodos(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "2") int size) {

        Pageable pageable = PageRequest.of(page, size);
        Page<Todo> todoPage = todoRepository.findAll(pageable);

        return ResponseEntity.ok(new MyApiResponse<>(true, todoPage, null));
    }
}

這個方法它接受兩個可選參數

  • page (頁碼,預設為 0 ),從 0 開始計算,為第一頁
  • size (每頁大小,預設為 2 ),為了測試方便,預設為 2

我們使用這些參數建立一個 pageable 物件,它定義了分頁的相關信息,然後將其傳遞給 repository 的 findAll 方法

findAll 方法會返回一個 Page<T> 物件,這是一個包含分頁結果的容器,除了當前頁面的內容,還包含了總頁數、總元素數等數據,方便在前端實現分頁導航

當實際使用 findAll 方法時,Spring Data JPA 會自動處理分頁的邏輯,產生適當的 SQL 查詢語法,只返回請求的那一頁的資料

測試

可以看到全部的資料有 3筆

沒有傳 page 的資料,預設為第一頁

傳入 page 的資料 1 ,為第二頁

動態排序

動態排序允許客戶端指定按照那個欄位進行排序,以及排序的方向(升序或降序)

這在處理大量的資料時特別有用,因為它允許用戶根據自己的需求來組織資料

修改 Controller

讓我們修改 TodoController 來支持動態排序

因為排序也被封裝在 Pageable 物件裡面,所以只需要調整 Controller 就好

@RestController
@RequestMapping("/api/todos")
public class TodoController {

    // 為了方便,在這裡只展示了所增加的相關程式碼

    @GetMapping("/paged")
    public ResponseEntity<MyApiResponse<Page<Todo>>> getPagedAndSortedTodos(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "2") int size,
            @RequestParam(defaultValue = "id") String sortBy,
            @RequestParam(defaultValue = "asc") String direction) {

        Sort.Direction sortDirection = direction.equalsIgnoreCase("desc") ? Sort.Direction.DESC : Sort.Direction.ASC;
        Sort sort = Sort.by(sortDirection, sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);
        Page<Todo> todoPage = todoRepository.findAll(pageable);

        return ResponseEntity.ok(new MyApiResponse<>(true, todoPage, null));
    }
}

在原本的方法中,我們增加了兩個新的參數

  • sortBy:指定要排序的欄位(預設為 id )
  • direction:指定排序方向,可以是 asc (升序) 或 desc  (降序) (預設為 asc

我們使用這兩個參數建立一個 Sort 物件,然後將其與頁碼頁面大小一起用來建立 Pageable 物件

這樣,我們就可以在一個請求中同時實現分頁和排序

測試

把分頁和排序一起測試

按 id 降序排序,取得第一頁

按 id 降序排序,取得第二頁

分頁和動態排序的優缺點

優點

  • 提高效能:只加載和處理必要的資料
  • 提升用戶體驗:允許用戶靈活地瀏覽和組織資料
  • 減少服務器負載:避免一次性加載大量資料
  • 靈活性:可以輕鬆地改變頁面大小、排序方式等

缺點

  • 增加複雜性:需要在前端和後端都處理分頁和排序邏輯
  • 可能的性能問題:對於非常大的資料,即使是分頁查詢也可能很慢
  • 一致性挑戰:在高併發環境下,不同頁面間的資料可能不一致

結論

通過實現分頁和動態排序,我們大大提高了應用程式處理大量數據的能力

  • 分頁可以減少每次請求需要處理的資料量,從而提高回應速度和減少資源消耗

  • 動態排序則為用戶提供了更靈活的資料查看方式,提升了用戶體驗

這些功能在實際應用中非常重要,特別是在處理大型資料或需要提供靈活查詢功能的場景中

通過 Spring Data JPA,我們可以輕鬆地實現這些複雜的功能,而無需編寫大量的程式碼

同步刊登於 iTHome 鐵人賽 「Spring Boot API 開發:從 0 到 1」Day 23 JPA 實現分頁與動態排序

圖片來源:AI 產生

參考連結