Spring JPA 查詢建立
Spring JPA 查詢建立
這是JPA
內容的核心部分,可以收藏用作參閱文件。
1. 查詢轉化和關鍵字
例:一個JPA查詢的轉化
public interface UserRepository extends Repository<User, Long> {
List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}
我們使用JPA 標準API建立一個查詢,但從本質上講,這將轉換為以下查詢:select u from User u where u.emailAddress = ?1 and u.lastname = ?2
下表描述了JPA支援的關鍵字,以及包含該關鍵字的方法可以轉換成什麼查詢語句:
表:查詢關鍵字及對應查詢語句
關鍵字 | 樣例 | JPQL片段(轉化的查詢語句) |
---|---|---|
And |
findByLastnameAndFirstname |
… where x.lastname = ?1 and x.firstname = ?2 |
Or |
findByLastnameOrFirstname |
… where x.lastname = ?1 or x.firstname = ?2 |
Is , Equals |
findByFirstname findByFirstnameIs ,findByFirstnameEquals |
… where x.firstname = ?1 |
Between |
findByStartDateBetween |
… where x.startDate between ?1 and ?2 |
LessThan |
findByAgeLessThan |
… where x.age < ?1 |
LessThanEqual |
findByAgeLessThanEqual |
… where x.age <= ?1 |
GreaterThan |
findByAgeGreaterThan |
… where x.age > ?1 |
GreaterThanEqual |
findByAgeGreaterThanEqual |
… where x.age >= ?1 |
After |
findByStartDateAfter |
… where x.startDate > ?1 |
Before |
findByStartDateBefore |
… where x.startDate < ?1 |
IsNull , Null |
findByAge(Is)Null |
… where x.age is null |
IsNotNull , NotNull |
findByAge(Is)NotNull |
… where x.age not null |
Like |
findByFirstnameLike |
… where x.firstname like ?1 |
NotLike |
findByFirstnameNotLike |
… where x.firstname not like ?1 |
StartingWith |
findByFirstnameStartingWith |
… where x.firstname like ?1 (引數繫結附加 % ) |
EndingWith |
findByFirstnameEndingWith |
… where x.firstname like ?1 (引數繫結附加 % ) |
Containing |
findByFirstnameContaining |
… where x.firstname like ?1 (引數繫結附加 % ) |
OrderBy |
findByAgeOrderByLastnameDesc |
… where x.age = ?1 order by x.lastname desc |
Not |
findByLastnameNot |
… where x.lastname <> ?1 |
In |
findByAgeIn(Collection<Age> ages) |
… where x.age in ?1 |
NotIn |
findByAgeNotIn(Collection<Age> ages) |
… where x.age not in ?1 |
True |
findByActiveTrue() |
… where x.active = true |
False |
findByActiveFalse() |
… where x.active = false |
IgnoreCase |
findByFirstnameIgnoreCase |
… where UPPER(x.firstame) = UPPER(?1) |
In
和NotIn
也接受集合的任何子類以及陣列作為一個引數或可變引數。對於相同邏輯運算子的其他語法版本,請檢查儲存庫查詢關鍵字。
2. 使用@Query
自定義查詢
使用自命名查詢宣告實體的查詢是一種有效的方法,該方法適用於少量查詢。由於查詢本身繫結到執行它們的Java方法上,實際上可以通過使用Spring Data JPA @Query
註釋直接繫結,而不用將它們註釋到域類。這將域類從特定於永續性的資訊中解放出來,並將查詢合併到該儲存庫介面:
註釋@Query
查詢優先於使用@NamedQuery
定義的查詢和在orm.xml
中宣告的自命名查詢。
例:使用@Query
在查詢方法上宣告查詢
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}
3. 使用高階LIKE
表示式
使用@Query
建立的自命名查詢的查詢執行機制允許在查詢定義中定義高階LIKE
表示式,如下面的示例所示:
例:@Query
中定義的LIKE
表示式
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.firstname like %?1")
List<User> findByFirstnameEndsWith(String firstname);
}
在前面的示例中,識別了LIKE
的分隔符字元(%
),並將查詢轉換為有效的JPQL查詢(移除%
)。在執行查詢時,傳遞給方法呼叫的引數將使用之前識別的LIKE
模式進行擴充。
4. 使用原生查詢
將nativeQuery
標誌設定為true, @Query
註釋允許執行原生查詢,如下面的示例所示:
例:使用@Query
在查詢方法上宣告一個原生查詢
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
User findByEmailAddress(String emailAddress);
}
Spring Data JPA目前不支援原生查詢的動態排序,因為它必須操作宣告的實際查詢,而這對本地SQL來說是不可靠的。但是,您可以通過自己指定count查詢來對本機查詢的結果進行分頁,如下面的示例所示:
例:通過使用@Query
在查詢方法上宣告用於分頁的本機計數查詢
public interface UserRepository extends JpaRepository<User, Long> {
@Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}
5.使用Sort
我們可以通過PageRequest
和Sort
直接完成排序,Sort
的Order
例項中實際使用的屬性需要與您的域模型(持久化模型)匹配。這意味著它們需要解析為查詢中使用的屬性或別名。JPQL將其定義為狀態欄位路徑表示式。
使用任何不可引用的路徑表示式都會導致異常。
但是,使用Sort
和@Query
可以讓您插入包含Order BY
子句在內的函式非路徑檢查的Order
例項,您可以使用JpaSort
。新增可能不安全的排序。
例:使用Sort
和JpaSort
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.lastname like ?1%")
List<User> findByAndSort(String lastname, Sort sort);
@Query("select u.id, LENGTH(u.firstname) as fn_len from User u where u.lastname like ?1%")
List<Object[]> findByAsArrayAndSort(String lastname, Sort sort);
}
repo.findByAndSort("lannister", new Sort("firstname")); //在域模型中指向屬性的有效排序表示式
repo.findByAndSort("stark", new Sort("LENGTH(firstname)")); //包含函式呼叫的無效排序。Thows 異常
repo.findByAndSort("targaryen", JpaSort.unsafe("LENGTH(firstname)")); //包含顯式不安全順序的有效排序。
repo.findByAsArrayAndSort("bolton", new Sort("fn_len")); //指向別名函式的有效排序表示式。
6.使用(自)命名引數
預設情況下,Spring Data JPA
使用基於位置的引數繫結,如上面的所有示例所述,即引數和?的位置一一順序對應。這使得查詢方法在重構引數位置時容易出錯。要解決這個問題,可以使用@Param
註釋為方法引數提供一個具體名稱,並在查詢中繫結該名稱,如下面的示例所示:
例:使用命名引數
public interface UserRepository extends JpaRepository<User, Long> {
@Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
User findByLastnameOrFirstname(@Param("lastname") String lastname,
@Param("firstname") String firstname);
}
這樣子就不需要再保證位置的一一對應了,只需要保證名稱的對應即可,方法引數根據它們在定義的查詢中的順序進行切換
參考文件
1.翻譯:【JPA Query Methods】