日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring Data JPA 从入门到精通~查询结果的处理

發布時間:2024/7/23 javascript 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Data JPA 从入门到精通~查询结果的处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參數選擇(Sort/Pageable)分頁和排序

?

特定類型的參數,Pageable 并動態 Sort 地將分頁和排序應用于查詢

案例:在查詢方法中使用 Pageable、Slice 和 Sort。

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);

第一種方法允許將 org.springframework.data.domain.Pageable 實例傳遞給查詢方法,以動態地將分頁添加到靜態定義的查詢中,Page 知道可用的元素和頁面的總數,它通過基礎框架里面觸發計數查詢來計算總數。由于這可能是昂貴的,這取決于所使用的場景,說白了,當用到 Pageable 的時候會默認執行一條 cout 語句。而 Slice 的用作是,只知道是否有下一個 Slice 可用,不會執行count,所以當查詢較大的結果集時,只知道數據是足夠的,而相關的業務場景也不用關心一共有多少頁。

排序選項也通過 Pageable 實例處理,如果只需要排序,需在 org.springframework.data.domain.Sort 參數中添加一個參數即可,正如看到的,只需返回一個 List 也是可能的。在這種情況下,Page 將不會創建構建實際實例所需的附加元數據(這反過來意味著必須不被發布的附加計數查詢),而僅僅是限制查詢僅查找給定范圍的實體。

限制查詢結果

案例:在查詢方法上加限制查詢結果的關鍵字 First 和 top。

User findFirstByOrderByLastnameAsc(); User findTopByOrderByAgeDesc(); 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);

查詢方法的結果可以通過關鍵字來限制 first 或 top,其可以被可互換使用,可選的數值可以追加到頂部/第一個以指定要返回的最大結果的大小。如果數字被省略,則假設結果大小為 1,限制表達式也支持 Distinct 關鍵字。此外,對于將結果集限制為一個實例的查詢,支持將結果包裝到一個實例中 Optional。如果將分頁或切片應用于限制查詢分頁(以及可用頁數的計算),則在限制結果中應用。

查詢結果的不同形式(List/Stream/Page/Future)

Page 和 List 在上面的案例中都有涉及下面將介紹的幾種特殊的方式。

流式查詢結果

可以通過使用 Java 8 Stream<T> 作為返回類型來逐步處理查詢方法的結果,而不是簡單地將查詢結果包裝在 Stream 數據存儲中,特定的方法用于執行流。

示例:使用 Java 8 流式傳輸查詢的結果 Stream<T>。

@Query("select u from User u") Stream<User> findAllByCustomQueryAndStream(); Stream<User> readAllByFirstnameNotNull(); @Query("select u from User u") Stream<User> streamAllPaged(Pageable pageable);

注意:流的關閉問題,try catch?是一種用關閉方法。

Stream<User> stream; try {stream = repository.findAllByCustomQueryAndStream()stream.forEach(…); } catch (Exception e) {e.printStackTrace(); } finally {if (stream!=null){stream.close();} }

異步查詢結果

可以使用 Spring 的異步方法執行功能異步執行存儲庫查詢,這意味著方法將在調用時立即返回,并且實際的查詢執行將發生在已提交給 Spring TaskExecutor 的任務中,比較適合定時任務的實際場景。

@Async Future<User> findByFirstname(String firstname); (1) @Async CompletableFuture<User> findOneByFirstname(String firstname); (2) @Async ListenableFuture<User> findOneByLastname(String lastname);(3)
  • 使用 java.util.concurrent.Future 的返回類型。
  • 使用 java.util.concurrent.CompletableFuture 作為返回類型。
  • 使用 org.springframework.util.concurrent.ListenableFuture 作為返回類型。

所支持的返回結果類型遠不止這些,可以根據實際的使用場景靈活選擇,其中 Map 和 Object[] 的返回結果也支持,這種方法不太推薦使用,應為沒有用到對象思維,不知道結果里面裝的是什么。

下表列出了 Spring Data JPA Query Method 機制支持的方法的返回值類型。

某些特定的存儲可能不支持全部的返回類型。 只有支持地理空間查詢的數據存儲才支持 GeoResult、GeoResults、GeoPage 等返回類型。

而我們要看引用的那個 Spring Data 的實現子模塊,以 Spring Data JPA 為例,看看 JPA 默認幫實現了哪些返回值類型。

還是通過工具分析 JpaRepository 幫我們實現了哪些返回類型,這樣不至于直接看官方文檔的時候一頭霧水。

Projections 對查詢結果的擴展

Spring JPA 對 Projections 的擴展的支持,個人覺得這是個非常好的東西,從字面意思上理解就是映射,指的是和 DB 的查詢結果的字段映射關系。一般情況下,我們是返回的字段和 DB 的查詢結果的字段是一一對應的,但有的時候,需要返回一些指定的字段,不需要全部返回,或者返回一些復合型的字段,還得自己寫邏輯。Spring Data 正是考慮到了這一點,允許對專用返回類型進行建模,以便更有選擇地將部分視圖對象。

假設 Person 是一個正常的實體,和數據表 Person 一一對應,我們正常的寫法如下:

@Entity class Person {@IdUUID id;String firstname, lastname;Address address;@Entitystatic class Address {String zipCode, city, street;} } interface PersonRepository extends Repository<Person, UUID> {Collection<Person> findByLastname(String lastname); }

(1)但是我們想僅僅返回其中的 name 相關的字段,應該怎么做呢?如果基于 projections 的思路,其實是比較容易的。只需要聲明一個接口,包含我們要返回的屬性的方法即可。如下:

interface NamesOnly {String getFirstname();String getLastname(); }

Repository 里面的寫法如下,直接用這個對象接收結果即可,如下:

interface PersonRepository extends Repository<Person, UUID> {Collection<NamesOnly> findByLastname(String lastname); }

Ctroller 里面直接調用這個對象可以看看結果。

原理是,底層會有動態代理機制為這個接口生產一個實現實體類,在運行時。

(2)查詢關聯的子對象,一樣的道理,如下:

interface PersonSummary {String getFirstname();String getLastname();AddressSummary getAddress();interface AddressSummary {String getCity();} }

(3)@Value 和 SPEL 也支持:

interface NamesOnly {@Value("#{target.firstname + ' ' + target.lastname}")String getFullName();… }

PersonRepository 里面保持不變,這樣會返回一個 firstname 和 lastname 相加的只有 fullName 的結果集合。

(4)對 Spel 表達式的支持遠不止這些:

@Component class MyBean {String getFullName(Person person) {…//自定義的運算} } interface NamesOnly {@Value("#{@myBean.getFullName(target)}")String getFullName();… }

(5)還可以通過 Spel 表達式取到方法里面的參數的值。

interface NamesOnly {@Value("#{args[0] + ' ' + target.firstname + '!'}")String getSalutation(String prefix); }

(6)這時候有人會在想,只能用 interface 嗎?dto 支持嗎?也是可以的,也可以定義自己的 Dto 實體類,需要哪些字段我們直接在 Dto 類當中暴漏出來 get/set 屬性即可,如下:

class NamesOnlyDto {private final String firstname, lastname; //注意構造方法NamesOnlyDto(String firstname, String lastname) {this.firstname = firstname;this.lastname = lastname;}String getFirstname() {return this.firstname;}String getLastname() {return this.lastname;} }

(7)支持動態 Projections,想通過泛化,根據不同的業務情況,返回不通的字段集合。

PersonRepository做一定的變化,如下:

interface PersonRepository extends Repository<Person, UUID> {Collection<T> findByLastname(String lastname, Class<T> type); }

我們的調用方,就可以通過 class 類型動態指定返回不同字段的結果集合了,如下:

void someMethod(PersonRepository people) { //我想包含全字段,就直接用原始entity(Person.class)接收即可Collection<Person> aggregates = people.findByLastname("Matthews", Person.class); //如果我想僅僅返回名稱,我只需要指定Dto即可。Collection<NamesOnlyDto> aggregates = people.findByLastname("Matthews", NamesOnlyDto.class); }

最后,Projections 的應用場景還是挺多的,望大家好好體會,這樣可以實現更優雅的代碼,去實現不同的場景。不必要用數組,冗余的對象去接收查詢結果。

總結

以上是生活随笔為你收集整理的Spring Data JPA 从入门到精通~查询结果的处理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。