1. 程式人生 > >Spring Data JPA 11.細節與增強

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 {

}