Spring Data JPA 11.細節與增強
細節與增強
細節
關鍵字使用細節
Like 與 NotLike
- 使用時,在傳入查詢引數時,需要用%%修飾才能夠正確的查詢到資料.
public void testMyDataJPA(){
List<Person> people = personRepository.findByLastNameLike("%C%") ;
// List<Person> people = personRepository.findByLastNameNotLike("%C%") ;
System.out.println(people);
}
StartingWith,EndingWith,Containing
- 使用時不需要用%%修飾.
- StartingWith:以xxx開頭的資料.
- EndingWith:以xxx結尾的資料.
- Containing:包含xxx資料,同Like.
List<Person> persons = personRepository.getByLastNameStartingWithAndIdLessThan("A", 5);
System. out.println(persons);
List<Person> persons2 = personRepository.getByLastNameEndingWithAndIdLessThan("C", 40);
System.out.println(persons2);
方法解析器
- 支援IgnoreCase為各個屬性(例如findByLastnameIgnoreCase(…))或支援忽略大小寫的型別(String例如,通常為例項)的所有屬性設定標誌findByLastnameAndFirstnameAllIgnoreCase(…)。是否支援忽略大小寫可能因商店而異,因此請參閱參考文件中有關特定於商店的查詢方法的相關章節。
SpEL表示式
-
從Spring Data JPA 1.4版開始,我們支援在手動定義的查詢中使用受限制的SpEL模板表示式@Query。在執行查詢時,將根據預定義的變數集評估這些表示式。Spring Data JPA支援一個名為的變數entityName。它的用法是select x from #{#entityName} x。它插入entityName與給定儲存庫關聯的域型別。該entityName解決如下:如果域型別已設定的name屬性@Entity的註釋,它被使用。否則,使用域型別的簡單類名。
-
當然,您可以User直接在查詢宣告中使用,但這也需要您更改查詢。引用#entityName將User類的潛在未來重對映到不同的實體名稱(例如,通過使用@Entity(name = “MyUser”)。
@Query("select p from #{#entityName} p where p.lastName = ?1")
List<Person> findByLastNameT(String lastName) ;
可空性註釋
-
您可以使用Spring Framework的可空性註釋來表達儲存庫方法的可空性約束。它們null在執行時提供了一種工具友好的方法和選擇性檢查,如下所示:
-
@NonNullApi:在包級別上使用,以宣告引數和返回值的預設行為是不接受或生成null值。
-
@NonNull:用於必須不是的引數或返回值null (引數上不需要,返回值@NonNullApi適用)。
-
@Nullable:用於可以的引數或返回值null。
-
Spring註釋是使用JSR 305註釋進行元註釋的(一種休眠但廣泛傳播的JSR)。JSR 305元註釋允許IDEA,Eclipse和Kotlin等工具供應商以通用方式提供空安全支援,而無需對Spring註釋進行硬編碼支援。要為查詢方法啟用執行時檢查可空性約束,需要使用Spring的@NonNullApiin 來啟用包級別的非可空性
-
一旦存在非空預設,就會在執行時驗證儲存庫查詢方法呼叫的可空性約束。如果查詢執行結果違反了定義的約束,則丟擲異常。當方法返回null但宣告為非可空時(預設情況下,儲存庫所在的包中定義了註釋)會發生這種情況。如果您想再次選擇可以為空的結果,請有選擇地使用@Nullable單個方法。使用本節開頭提到的結果包裝器型別繼續按預期工作:將空結果轉換為表示缺席的值。
package com.acme;
import org.springframework.lang.Nullable;
interface UserRepository extends Repository<User, Long> {
// 在執行時不產生結果的查詢時丟擲一個EmptyResultDataAccessException。當emailAddress為null時丟擲一個IllegalArgumentException。
User getByEmailAddress(EmailAddress emailAddress);
//null執行查詢時不返回結果。也接受null作為的值emailAddress
@Nullable
User findByEmailAddress(@Nullable EmailAddress emailAdress);
//Optional.empty()執行查詢時不返回結果。當emailAddress為null時丟擲一個IllegalArgumentException
Optional<User> findOptionalByEmailAddress(EmailAddress emailAddress);
}
分頁和排序
//方法名直接sql查詢條件,引數中帶有Pageable則會分頁(同時可以帶有排序)
Page<User> findByLastName(String lastName, Pageable pageable);
Slice<User> findByLastName(String lastName, Pageable pageable);
List<User> findByLastName(String lastName, Sort sort);
List<User> findByLastName(String lastName, Pageable pageable);
Page<Person> findByLastNameContaining(String lastName, Pageable pageable);
限制查詢結果
- 查詢方法的結果可以通過使用first或top關鍵字來限制,這些關鍵字可以互換使用。可以附加一個可選的數值,top或者first指定要返回的最大結果大小。如果省略該數字,則假定結果大小為1。以下示例顯示如何限制查詢大小:
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
//方法名直接sql查詢條件,引數中帶有Pageable則會分頁(同時可以帶有排序)
Page<User> queryFirst10ByLastName(String lastName, Pageable pageable);
Slice<User> findTop3ByLastName(String lastName, Pageable pageable);
List<User> findFirst10ByLastName(String lastname, Sort sort);
List<User> findTop10ByLastName(String lastname, Pageable pageable);
預測
-
Spring Data查詢方法通常返回由儲存庫管理的聚合根的一個或多個例項。但是,有時可能需要根據這些型別的某些屬性建立投影。Spring Data允許建模專用返回型別,以更有選擇地檢索托管聚合的部分檢視。
-
Entity實體:
public class Person {
private Integer id ;
private String lastName ;
private String email ;
private Date birth ;
private Integer age ;
//...
現在假設我們只想檢索人的姓名和郵箱。
(1)基於介面的預測:將查詢結果限制為僅名稱屬性的最簡單方法是宣告一個介面,該介面公開要讀取的屬性的訪問器方法
- 投影介面
//用於檢索屬性子集的投影介面
public interface LastNameAndEmailOnly {
String getLastName() ;
String getEmail() ;
}
//這裡重要的一點是,此處定義的屬性與聚合根中的屬性完全匹配。這樣做可以新增查詢方法
- dao使用:
List<LastNameAndEmailOnly> findByLastName(String lastName) ;
- 可以遞迴使用預測。如果您還想包含一些Address資訊,請為其建立一個投影介面,並從宣告中返回該介面getAddress(),如以下示例所示:
interface PersonSummary {
String getLastName() ;
String getEmail() ;
AddressSummary getAddress();
interface AddressSummary {
String getCity();
}
}
(2)基於類別的預測(DTO)
- 定義投影的另一種方法是使用值型別DTO(資料傳輸物件),它包含應該檢索的欄位的屬性。這些DTO型別可以與投影介面完全相同的方式使用,除了不發生代理並且不能應用巢狀投影。
如果儲存通過限制要載入的欄位來優化查詢執行,則要載入的欄位將根據公開的建構函式的引數名稱確定。
以下示例顯示了投影DTO:
public class PersonDTO {
private final String lastName;
private final String email;
public PersonDTO(String lastName, String email) {
this.lastName = lastName;
this.email = email;
}
public String getLastName() {
return lastName;
}
public String getEmail() {
return email;
}
}
//避免投影DTO的樣板程式碼您可以使用Project Lombok大大簡化DTO的程式碼,
//它提供了一個@Value註釋(不要與@Value之前的介面示例中顯示的Spring的註釋混淆)
按示例查詢(QBE)
-
按示例查詢非常適合幾種用例:
-
使用一組靜態或動態約束查詢資料儲存。
-
頻繁重構域物件,而不必擔心破壞現有查詢。
-
獨立於底層資料儲存API工作。
-
按示例查詢也有幾個限制:
-
不支援巢狀或分組的屬性約束,例如firstname = ?0 or (firstname = ?1 and lastname = ?2)。
-
僅支援字串的開始/包含/結束/正則表示式匹配以及其他屬性型別的精確匹配。
-
例子:
erson person = new Person();
person.setLastName("Dave");
Example<Person> example = Example.of(person);
- 示例不限於預設設定。您可以使用,為字串匹配,空值處理和特定於屬性的設定指定自己的預設值ExampleMatcher:具體參考文件
鎖定
- 要指定要使用的鎖定模式,可以@Lock在查詢方法上使用註釋,如以下示例所示:
@Lock(LockModeType.READ)
PersonDTO findByLastName(String lastName) ;
//這個方法宣告將導致觸發查詢中配備了LockModeType的READ
審計
基本
-
Spring Data提供了複雜的支援,可以透明地跟蹤建立或更改實體的人員以及更改發生的時間。要從該功能中受益,您必須為您的實體類配備審計元資料,該元資料可以使用註釋或通過實現介面來定義。
-
基於註釋的審計元資料
我們提供@CreatedBy和@LastModifiedBy捕捉誰建立或修改的實體以及使用者@CreatedDate和@LastModifiedDate捕捉時的變化發生了。
JPA審計
- 配置:Spring Data JPA附帶了一個實體監聽器,可用於觸發審計資訊的捕獲。首先,您必須註冊AuditingEntityListener要用於orm.xml檔案中永續性上下文中的所有實體.
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="….data.jpa.domain.support.AuditingEntityListener" />
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
- 您還可以AuditingEntityListener使用@EntityListeners註釋在每個實體的基礎上啟用,如下所示:
@Entity
@EntityListeners(AuditingEntityListener.class)
public class MyEntity {
}