兩行代碼玩轉Spring Data排序和分頁

兩行代碼玩轉Spring Data排序和分頁

Spring Data


一:嘮嗑

在實際項目中對Spring Data的各種使用相當多,簡單的增刪改查Spring Data提供了現成的方法,一些複雜的,我們可以在接口方法寫And,Not等關鍵字來搞定,想寫原生SQL,CQL(Neo4j),Query DSL (Elasticsearch)的,直接使用@Query(“……”)註解搞定,真的是方便到不行!

本篇博客不打算講Spring Data如何使用,不同的模塊(JPA,Neo4j….)使用也略不相同,但Spring Data的排序Sort和分頁Pageable接口都是差不多的,所以帶大家搞明白搞明白Spring Data的排序和分頁是如何使用的。

二:介紹

Spring Data的任務是為數據訪問提供一個熟悉的、一致的、基於Spring的編程模型,同時仍然保留底層數據存儲的特殊特性。

Spring Data 項目的目的是為了簡化構建基於 Spring 框架應用的數據訪問計數,包括非關係數據庫、Map-Reduce 框架、雲數據服務等等;另外也包含對關係數據庫的訪問支持。

SpringData讓數據訪問變得更加方便。

三:模塊

Spring Data

  • Spring Data for Apache Cassandra
  • Spring Data Commons
  • Spring Data Couchbase
  • Spring Data Elasticsearch
  • Spring Data Envers
  • Spring Data for Pivotal GemFire
  • Spring Data Graph
  • Spring Data JDBC
  • Spring Data JDBC Extensions
  • Spring Data JPA
  • Spring Data LDAP
  • Spring Data MongoDB
  • Spring Data Neo4J
  • Spring Data Redis
  • Spring Data REST
  • Spring Data for Apache Solr
  • Spring for Apache Hadoop

四:排序

通過一行代碼就可以快速使用:

Sort sort = new Sort(Sort.Direction.DESC, "id");


在Sort類中定義了一個枚舉類型Direction,該枚舉類型聲明瞭兩個常量ASC,DESC定義方向。該構造方法的第一個參數指明方向降序(DESC)或升序(ASC),第二個參數指明以id列的值為準進行排序。

你也可以創建一個多屬性的Sort實例。

Sort(Sort.Direction direction, List properties)
Sort(String... properties)

不過官方已經棄用該方法,推薦使用

public static Sort by(String... properties)
public static final Direction DEFAULT_DIRECTION = Direction.ASC;

Sort的一些方法


兩行代碼玩轉Spring Data排序和分頁

Spring Data


Sort.Order

Sort.Order是Sort的一個靜態內部類,官方說明是:PropertyPath實現了排序的配對。方向和屬性。它用於提供排序的輸入 。

簡單來講,你可以定義一個Order,在需要時傳入order構建Sord實例。

Order(Sort.Direction direction, String property)


更獨特的使用是加入自己的空處理提示的枚舉:

Order(Sort.Direction direction, String property, Sort.NullHandling nullHandlingHint)


Sort.NullHandling是可用於排序表達式的空處理提示的枚舉。對使用的數據存儲的一種提示,用於在非空條目之後對具有空值的條目進行排序。

在需要Sort時,可通過Order創建:

Sort(Sort.Order... orders)

Sort.Order的一些方法:


兩行代碼玩轉Spring Data排序和分頁

Spring Data


兩行代碼玩轉Spring Data排序和分頁

Spring Data


如果你還想全面瞭解它的使用,推薦閱讀官方英文文檔:

https://docs.spring.io/spring-data/data-commons/docs/current/api/org/springframework/data/domain/Sort.html

五:分頁

Pageable只是 Spring Data 提供的分頁信息的抽象接口。

實現類:

  1. AbstractPageRequest:抽象類。供PageRequest和QPageRequest繼承。
  2. PageRequest: 基本的可頁面化Java Bean實現。
  3. QPageRequest:基本的Java Bean實現,可以支持QueryDSL。

分頁功能也只需要一行代碼:

Pageable pageable = new PageRequest(int page, int size, Sort sort);

page - 從零開始的索引頁

size- 要返回的頁面的大小

sort - 排序

你也可以創建沒有排序的分頁

PageRequest(int page, int size) 


更方便的是可以一行代碼創建有排序方向和屬性的分頁

PageRequest(int page, int size, Sort.Direction direction, String... properties)


如果你使用的是2.0以後的版本,官方已經棄用以上構造方法的形式,推薦使用靜態方法:


兩行代碼玩轉Spring Data排序和分頁

Spring Data


比如我們想遍歷整個數據表,就可以使用分頁遍歷,這樣不至於一次把數據全部加載到內存。


兩行代碼玩轉Spring Data排序和分頁

Spring Data


注意:在使用next()方法時,不要把pageable.next()直接作為參數傳入方法。

如repository.findAll(page.next())這樣的寫法會導致死循環。查看next()方法的源碼發現這個方法只是幫我們new了一個新的Pageable對象,原來的pageable還是沒啥變化。一直next()下去也只是在原地踏步。

 public Pageable next() {
return new PageRequest(getPageNumber() + 1, getPageSize(), getSort());
}

正確的寫法:

repository.findAll(pageable = pageable.next());


六:使用

Spring Data Jpa除了會通過命名規範幫助我們擴展Sql語句外,還會幫助我們處理類型為Pageable的參數,將pageable參數轉換成為sql語句中的條件,同時,還會幫助我們處理類型為Page的返回值,當發現返回值類型為Page,Spring Data Jpa將會把數據的整體信息、當前數據的信息,分頁的信息都放入到返回值中。這樣,我們就能夠方便的進行個性化的分頁查詢。

public interface UserRepository extends JpaRepository {
@Override
Page findAll(Pageable pageable);
}

如果你想用@Query寫原生查詢語句並實現分頁:

Spring Data JPA目前不支持原生查詢的動態排序,因為它必須操作聲明的實際查詢,這對於原生SQL是無法可靠地做到的。但是,您可以通過自己指定count查詢來使用原生查詢進行分頁,如下面的示例所示:

public interface UserRepository extends JpaRepository {
@Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page findByLastname(String lastname, Pageable pageable);
}

七:讀取

分頁查詢:

Page sampleEntities = userRepository.findAll(pageable);


接口Page繼承了接口Slice,話不多說,直接上乾貨!

總頁數

int getTotalPages()

元素的總數

long getTotalElements()

返回當前頁的索引(是第幾頁)

int getNumber()

返回作為List的頁面內容

List getContent()

返回當前在這個頁上的元素的數量

int getNumberOfElements()

返回用於請求當前頁的Pageable

default Pageable getPageable()

返回頁的大小。

int getSize()

返回頁的排序參數。

Sort getSort()

頁面是否有內容。

boolean hasContent()

是否有下一頁。

boolean hasNext()

是否有上一頁

boolean hasPrevious()

當前頁是否是第一個

boolean isFirst()

當前頁是否是最後一個

boolean isLast()

下一頁的Pageable

Pageable nextPageable()

上一頁的Pageable

Pageable previousPageable()

加Java架構師進階交流群獲取Java工程化、高性能及分佈式、高性能、深入淺出。高架構。性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的直播免費學習權限 都是大牛帶飛 讓你少走很多的彎路的 群號是:883922439 對了 小白勿進 最好是有開發經驗

注:加群要求

1、具有工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加。

2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。

3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的,可以加。

4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。

5.阿里Java高級大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶著大家全面、科學地建立自己的技術體系和技術認知!


分享到:


相關文章: