Spring Data Jpa (三)定義查詢方法

本章詳細講解如何利用方法名定義查詢方法(Defining Query Methods)算法

(1)定義查詢方法的配置方法spring

  因爲Spring JPA Repository的實現原理是採用動態代理的機制,因此咱們介紹兩種定義查詢方法:從方法名稱中能夠指定特定用於存儲的查詢和更新,或經過使用@Query手動定義的查詢,這個取決於實際存儲操做。只須要實體Repository繼承Spring Data Common裏面的Repository接口便可,就像前面咱們講的同樣。若是你想有其餘更多默認通用方法的實現,能夠選擇JpaRepository、PagingAndSortingRepository、CrudRepository等接口,也能夠直接繼承咱們後面要講的JpaSpecificationExecutor、QueryByExampleExecutor和自定義Response,均可以達到一樣的效果。api

  若是你不想擴展Spring數據接口,還可使用它來註解存儲庫接口@RepositoryDefinition。擴展CrudRepository公開了一套完整的方法來操縱實體。若是你但願對所暴露的方法有選擇性,只須要將暴露的方法複製CrudRepository到域庫中便可。其實也是自定義Repository的一種。架構

  看下面的示例,選擇性地暴露CRUD方法:框架

  在這個示例的第一步中爲全部域存儲庫定義了一個公共基礎接口,並將其暴露出來。findOne(…)和save(…)方法將被路由到由Spring Data提供的、你選擇的存儲庫的基本存儲庫實現中,例如JPA中的SimpleJpaRepository。由於它們正在匹配方法簽名CrudRepository,因此UserRepository將可以保存用戶,並經過id查找單個用戶信息,以及觸發查詢以經過其電子郵件地址查找Users。dom

 

(2)方法的查詢策略設置異步

  經過@EnableJpaRepositories(queryLookupStrategy=QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND)能夠配置方法的查詢策略,其中QueryLookupStrategy.Key的值一共有三個。3d

  CREATE:直接根據方法名進行建立。規則是根據方法名稱的構造進行嘗試,通常的方法是從方法名中刪除給定的一組已知前綴,並解析該方法的其他部分。若是方法名不符合規則,啓動的時候就會報異常。代理

  USE_DECLARED_QUERY:聲明方式建立,即本書說的註解方式。啓動的時候會嘗試找到一個聲明的查詢,若是沒有找到就將拋出一個異常。查詢能夠由某處註釋或其餘方法聲明。code

  CREATE_IF_NOT_FOUND:這個是默認的,以上兩種方式的結合版。先用聲明方式進行查找,若是沒有找到與方法相匹配的查詢,就用create的方法名建立規則建立一個查詢。

 除非有特殊需求,通常直接用默認的,不用管。配置示例以下

  

(3)查詢方法的建立

  內部基礎架構中有個根據方法名的查詢生成器機制,對於在存儲庫的實體上構建約束查詢頗有用。該機制方法的前綴有find…By、read…By、query…By、count…By和get…By,從這些方法能夠分析它的其他部分(實體裏面的字段)。引入子句能夠包含其餘表達式,例如在Distinct要建立的查詢上設置不一樣的標誌。然而,第一個By做爲分隔符來指示實際標準的開始。在一個很是基本的水平上,你能夠定義實體性條件,並與它們串聯(And和Or)。

  用一句話歸納,待查詢功能的方法名由查詢策略(關鍵字)、查詢字段和一些限制性條件組成。在以下例子中,能夠直接在controller裏面進行調用以查看效果:

  

  解析方法的實際結果取決於建立查詢的持久性存儲。可是,有一些常見的事項須要注意:

    表達式一般是能夠鏈接的運算符的屬性遍歷。你可使用組合屬性表達式AND和OR。你還能夠將運算關鍵字Between、LessThan、GreaterThan、Like做爲屬性表達式。受支持的操做員可能因數據存儲而異,所以請參閱官方參考文檔的相應部份內容。

    該方法解析器支持設置一個IgnoreCase標誌個別特性(例如,findByLastnameIgnoreCase(…))或支持忽略大小寫(一般是一個類型的全部屬性爲String的狀況下,例如,findByLastnameAndFirstnameAllIgnoreCase(…))。是否支持忽略示例可能會因存儲而異,所以請參閱參考文檔中的相關章節,瞭解特定於場景的查詢方法。

   能夠經過OrderBy在引用屬性和提供排序方向(Asc或Desc)的查詢方法中附加一個子句來應用靜態排序。要建立支持動態排序的查詢方法來影響查詢結果。

 

(4)關鍵字列表

   

 

 

 

 

 

 

 

 

 

 

 

注意,除了find的前綴以外,咱們查看PartTree的源碼,還有如
下幾種前綴:

  

使用的時候要配合不一樣的返回結果進行使用,例如:

  

 

(5)方法的查詢策略的屬性表達式

   屬性表達式(Property Expressions)只能引用託管(泛化)實體的直接屬性,如前一個示例所示。在查詢建立時,你已經確保解析的屬性是託管實體的屬性。同時,還能夠經過遍歷嵌套屬性定義約束。假設一個Person實體對象裏面有一個Address屬性裏面包含一個ZipCode屬性。在這種狀況下,方法名爲:

  建立及其查找的過程是:解析算法首先將整個part(AddressZipCode)解釋爲屬性,並使用該名稱(uncapitalized)檢查域類的屬性。若是算法成功,就使用該屬性。若是不是,就拆分右側駝峯部分的信號源到頭部和尾部,並試圖找出相應的屬性,在咱們的例子中是AddressZip和Code。若是算法找到一個具備頭部的屬性,那麼它須要尾部,並從那裏繼續構建樹,然後按照剛剛描述的方式將尾部分割。若是第一個分割不匹配,就將分割點移動到左邊(Address、ZipCode),而後繼續。

  雖然這在大多數狀況下應該起做用,可是算法可能會選擇錯誤的屬性。假設Person類也有一個addressZip屬性,該算法將在第一個分割輪中匹配,而且基本上會選擇錯誤的屬性,最後失敗(由於該類型addressZip可能沒有code屬性)。

  要解決這個歧義,能夠在方法名稱中手動定義遍歷點,因此咱們的方法名稱最終會是:

  固然Spring JPA裏面是將下劃線視爲保留字符,可是強烈建議遵循標準Java命名約定(不使用屬性名稱中的下劃線,而是使用駱駝示

例)。命名屬性的時候注意一下這個特性。

  

(6)查詢結果的處理

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

    1.特定類型的參數,動態地將分頁和排序應用於查詢

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

    

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

    排序選項也經過Pageable實例處理。若是隻須要排序,那麼在org.springframework.data.domain.Sort參數中添加一個參數便可。正如你能夠看到的,只返回一個List也是可能的。在這種狀況下,Page將不會建立構建實際實例所需的附加元數據(這反過來意味着必須不被髮布的附加計數查詢),而僅僅是限制查詢僅查找給定範圍的實體。

    2.限制查詢結果

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

    

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

  

  2.查詢結果的不一樣形式(List/Stream/Page/Future)

    Page和List在上面的示例中都有涉及,下面介紹幾種特殊的。

    1.流式查詢結果

      能夠經過使用Java 8 Stream<T>做爲返回類型來逐步處理查詢方法的結果,而不是簡單地將查詢結果包裝在Stream數據存儲中,特定的方法用於執行流。

    

    

    2.異步查詢結果

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

    

 3 Projections對查詢結果的擴展

    Spring JPA對Projections擴展的支持是很是好的。從字面意思上理解就是映射,指的是和DB查詢結果的字段映射關係。通常狀況下,返回的字段和DB查詢結果的字段是一一對應的,但有的時候,我們須要返回一些指定的字段,不須要所有返回,或者只返回一些複合型的字段,還要本身寫邏輯。Spring Data正是考慮到了這一點,允許對專用返回類型進行建模,以便咱們有更多的選擇,將部分字段顯示成視圖對象。

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

  

  (1)咱們想僅僅返回其中與name相關的字段,應該怎麼作呢?基於projections的思路,實際上是比較容易的。咱們只須要聲明一個

接口,包含要返回的屬性的方法便可,例如:

  

  Repository裏面的寫法以下,直接用這個對象接收結果便可

 

  在Controtroller裏面直接調用對象能夠查看結果。原理是運行時底層會有動態代理機制爲這個接口生成一個實現實體類。

  (2)查詢關聯的子對象,例如:

   

  (3)@Value和SPEL也支持:

    

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

相關文章
相關標籤/搜索