首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring Data JPA 方法命名查詢規則完整解析

     編輯:Java 相關知識

核心規則:方法名即查詢語意

Spring Data JPA 允許在 Repository 介面定義方法,框架自動解析方法名生成 JPQL/SQL。規則:find|read|get 開頭 + By + 屬性名 + 關鍵字組合。

關鍵字對照表

關鍵字SQL 對應範例
And / OrAND / ORfindByNameAndAge
Is / Equals=findByNameIs
BetweenBETWEENfindByAgeBetween
LessThan / LessThanEqual< / <=findByAgeLessThan
GreaterThan / GreaterThanEqual> / >=findByAgeGreaterThanEqual
After / Before> / < (時間)findByCreateTimeAfter
IsNull / IsNotNullIS NULL / IS NOT NULLfindByEmailIsNull
Like / NotLikeLIKE / NOT LIKEfindByNameLike (需自帶 %)
StartingWith / EndingWithLIKE 'xxx%' / LIKE '%xxx'findByNameStartingWith
ContainingLIKE '%xxx%'findByNameContaining
OrderBy...Asc/DescORDER BYfindByAgeOrderByNameDesc
Not<>findByNameNot
In / NotInIN / NOT INfindByIdIn
True / False= true / = falsefindByActiveTrue
IgnoreCaseLOWER() 比較findByNameIgnoreCase

方法名解析邏輯:從右往左貪婪匹配

// 假設實體:AccountInfo { User user; Address address; }
// 方法:findByUserAddressZip()

// 解析步驟:
1. 去掉前綴 findBy → "UserAddressZip"
2. 判斷 userAddressZip 是否為 AccountInfo 直接屬性 → 否
3. 從右截取首個大寫開頭單詞 "Zip" → 剩餘 "UserAddress"
4. 判斷 userAddress 是否為屬性 → 否
5. 繼續截取 "Address" → 剩餘 "User"
6. 判斷 user 為屬性 ✓ → 類型 User
7. 在 User 中找 addressZip → 找到 ✓
8. 最終解析:AccountInfo.user.addressZip

⚠️ 歧義問題:若同時存在 `user` 和 `userAddress` 屬性,會產生歧義。強烈建議用底線分隔層級:`findByUser_Address_Zip()`

特殊情況處理

1. 參數為 null 的行為

List<User> findByNameAndAge(String name, Integer age);
// 呼叫:repo.findByNameAndAge(null, 18)
// 生成 SQL:WHERE name IS NULL AND age = 18
// ⚠️ 不是忽略條件,而是精確匹配 NULL 值!

動態查詢請用 `@Query` 或 `Specification` / `QueryByExampleExecutor`。

2. 排序與分頁

// 靜態排序
List<User> findByAgeOrderByNameDesc(Integer age);

// 動態排序/分頁
Page<User> findByAge(Integer age, Pageable pageable);
List<User> findByAge(Integer age, Sort sort);

// 呼叫
repo.findByAge(18, PageRequest.of(0, 10, Sort.by("name").descending()));

3. 多表關聯查詢

// 實體關聯:Order { User user; }
// 方法:findByUserName(String name) → 查詢 user.name = ? 的訂單
// 更複雜關聯建議改用 @Query

實戰 Repository 範例

public interface UserRepository extends JpaRepository<User, Long> {
    // 基礎查詢
    List<User> findByName(String name);
    User findByEmail(String email);
    
    // 組合條件
    List<User> findByNameAndAgeGreaterThan(String name, int age);
    List<User> findByNameOrEmail(String name, String email);
    
    // 模糊/範圍
    List<User> findByNameContaining(String keyword);
    List<User> findByAgeBetween(int min, int max);
    List<User> findByCreateTimeAfter(LocalDateTime time);
    
    // 排序分頁
    List<User> findByStatusOrderByCreateTimeDesc(Integer status);
    Page<User> findByStatus(Integer status, Pageable pageable);
    
    // 集合條件
    List<User> findByIdIn(List<Long> ids);
    
    // 忽略大小寫
    User findByEmailIgnoreCase(String email);
}

進階:@Query 註解補足

當方法名過長、涉及複雜 JOIN、子查詢、原生 SQL 時,改用 `@Query`:

@Query("select u from User u where u.name like %:keyword% and u.age > :minAge")
List<User> search(@Param("keyword") String keyword, @Param("minAge") int minAge);

@Query(value = "select * from user where name = ?1", nativeQuery = true)
User findByNameNative(String name);

方法命名查詢適合單表、條件固定、語意清晰的簡單場景。複雜動態查詢請擁抱 `Specification`、`Querydsl` 或 `@Query`,別讓方法名變成「文檔」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved