Published on

「Spring Boot API 開發:從 0 到 1」Day 21 JPA 自定義查詢方法

Spring Data JPA 的自定義查詢方法是一個強大的功能,它允許開發者透過方法名稱來定義查詢邏輯

無需手動編寫 SQL 或 JPQL 查詢語句

這種方式不僅簡化了開發過程,還提高了代碼的可讀性和維護性

相關規則

  • 方法名稱必須以特定的關鍵字開頭,如 findBygetByqueryBycountBydeleteBy
  • 接著是實體屬性名稱,可以使用 AndOr 連接多個條件
  • 可以使用一些關鍵字來指定查詢條件,如 GreaterThanLessThanBetweenLikeIn
  • 可以在方法名稱結尾添加 OrderBy 來指定排序

範例

  • findByTitle(String title)
    • 根據標題查找
  • findByCompletedTrue()
    • 查找已完成的項目
  • findByTitleContainingAndCompletedFalse(String keyword)
    • 查找標題包含關鍵字且未完成的項目
  • findByCreatedAtBetween(Date start, Date end)
    • 查找在指定日期範圍內創建的項目
  • findByTitleOrderByCreatedAtDesc(String title)
    • 根據標題查找並按創建時間降序排序

修改程式碼

修改 Repository

讓我們修改之前的 TodoRepository,增加一些自定義查詢方法

public interface TodoRepository extends JpaRepository<Todo, Long> {

    // 根據標題查找待辦事項
    List<Todo> findByTitle(String title);

    // 查找所有已完成的待辦事項
    List<Todo> findByCompletedTrue();

    // 根據標題模糊查詢,並按 ID 降序排序
    List<Todo> findByTitleContainingOrderByIdDesc(String keyword);

    // 計算未完成的待辦事項數量
    long countByCompletedFalse();
}

修改 Controller

讓我們在 TodoController 中使用這些新方法

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

    // 為了方便,在這裡只展示了修改後,所增加的 DB 操作相關程式碼

    @GetMapping("/search")
    public ResponseEntity<MyApiResponse<List<Todo>>> searchTodos(@RequestParam String keyword) {
        List<Todo> todos = todoRepository.findByTitleContainingOrderByIdDesc(keyword);
        return ResponseEntity.ok(new MyApiResponse<>(true, todos, null));
    }

    @GetMapping("/completed")
    public ResponseEntity<MyApiResponse<List<Todo>>> getCompletedTodos() {
        List<Todo> completedTodos = todoRepository.findByCompletedTrue();
        return ResponseEntity.ok(new MyApiResponse<>(true, completedTodos, null));
    }

    @GetMapping("/count-incomplete")
    public ResponseEntity<MyApiResponse<Long>> getIncompleteCount() {
        long count = todoRepository.countByCompletedFalse();
        return ResponseEntity.ok(new MyApiResponse<>(true, count, null));
    }
}

測試

可以使用之前的 api-test.http 來測試

可以看到相關的測試結果

自定義查詢方法的優缺點

優點

  • 簡化代碼:無需手動編寫複雜的 SQL 或 JPQL 查詢,大大減少了樣板代碼
  • 提高可讀性:方法名稱直接反映了查詢邏輯,使程式碼更易於理解
  • 類型安全:編譯時檢查可以捕獲大多數錯誤,減少運行時錯誤
  • 靈活性:可以輕鬆建立各種複雜的查詢,而無需深入了解底層資料庫
  • 自動優化:Spring Data JPA 會自動優化產生的查詢,提高性能
  • 可測試性:易於為這些方法編寫單元測試

缺點

  • 學習曲線:需要熟悉命名約定和規則
  • 方法名稱可能變得冗長:對於非常複雜的查詢,方法名稱可能變得難以閱讀
  • 性能考慮:對於非常複雜或高度優化的查詢,手動編寫 SQL 可能更有效
  • 可能導致過度使用:可能會導致建立過多的特定查詢方法,而不是使用更通用的解決方案

最佳實務

  • 保持方法名稱簡潔:避免過長的方法名稱,複雜查詢考慮使用 @Query 註解
  • 善用 Spring Data JPA 的關鍵字:如 And、Or、Between、LessThan 等
  • 考慮查詢效能:對於頻繁使用的複雜查詢,可能需要手動優化或使用原生 SQL
  • 適當使用投影:只選擇需要的欄位,而不是總是返回整個實體
  • 利用測試:編寫單元測試確保查詢方法的正確性
  • 文件化:為複雜的查詢方法添加註解,說明其用途和任何特殊邏輯
  • 避免過度使用:不要為每個可能的查詢都建立方法,保持 Repository 的簡潔

結論

自定義查詢方法是 Spring Data JPA 的一個強大特性,能夠大大提高開發效率和程式碼品質

然而,開發者應該權衡其利弊,確保在簡便性和效能之間找到適當的平衡

對於簡單到中等複雜度的查詢,自定義查詢方法是一個極好的選擇

而對於更複雜的查詢邏輯,可能需要考慮使用 @Query 註解或甚至是 原生 SQL 查詢

同步刊登於 iTHome 鐵人賽 「Spring Boot API 開發:從 0 到 1」Day 21 JPA 自定義查詢方法

圖片來源:AI 產生

參考連結