天天看點

Spring Data JPA漸進式學習--如何自定義查詢方法呢?

作者:是啊超ya

1 定義查詢方法的配置和使用方法

在Spring Data JPA中可以直接通過方法名實作CRUD

通過方法名實作CRUD

想要通過方法名實作CRUD的話,需要讓我們的UserRepisitory繼承CrudRepository,如下所示

public interface UserRepository extends CrudRepository<UserInfo,Integer> {

}

           

然後在service層就可以調用UserRepository裡的方法了

Spring Data JPA漸進式學習--如何自定義查詢方法呢?

選擇性暴露CRUD方法

有時候我們不希望所有的方法都暴露出來,當有些資料隻想被檢視而不想被修改的時候,就可以如此。

具體操作就是,繼承Repository類,自己寫方法。

public interface UserRepository extends Repository<UserInfo,Integer> {
    UserInfo findOne();
    List<UserInfo> findAll();
}

           

這時在controller裡調用的話,就隻有這兩個方法了。

Spring Data JPA漸進式學習--如何自定義查詢方法呢?

2 方法的查詢政策設定

通過@EnableJpaRepositories可以配置方法的查詢政策,這個一般不會更改,預設的就可以。

@EnableJpaRepositories(queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND)

           

這裡可以選擇的QueryLookupStrategy.Key的值共有三個

Create

Create 直接根據方法名進行建立,如UserInfo findByAgeAndName();會删除findBy字元,然後解析Age,And,Name.若是方法名不符合規則,則會報錯。在這種政策模式下,配置了@Query也是沒用的,隻會解析方法名。

USE_DECLARED_QUERY

聲明方式建立,這種政策模式下,必須配置Query,如下所示,并不會去解析方法名,

@Query("select u from UserInfo u")
UserInfo getAllList();

           

CREATE_IF_NOT_FOUND

這個則是以上兩種情況的綜合,會先去聲明方式進行建立,若是沒有,則解析方法名來建立一個查詢。若是兩者都不滿足,則啟動會報錯。這是預設的查詢政策。

3 定義查詢方法的文法

帶查詢功能的方法名由查詢政策+查詢字段+一些限制性條件語義清晰,功能完整。下表是DMQ文法常用的關鍵字清單。

Spring Data JPA漸進式學習--如何自定義查詢方法呢?

再舉一兩個例子來說明一下。

//去重,and的用法
List<UserInfo> findDistinctByAddressAndName();

//根據name查找,并根據ID進行逆序排列
List<UserInfo> findByNameOrderByIdDesc();

           

雖然表中都是以find開頭的,但是JPA還支援read,get,query,stream,count,exist,delete,remove等字首,如字面意思一樣使用即可。

4 特定類型的參數:Sort和Pageable

為了支援排序和分頁,JPA支援了兩個特殊類型的參數,Sort和Pageable。

Sort在查詢的時候可以實作動态排序,并且決定了字段排序的方向。 Pageable可以實作分頁和排序的雙重效果。

接口定義方法與說明:

1 分頁和總數

Page<UserInfo> findByName(String name, Pageable pageable);

           

這個傳回将包含可用的元素和頁面的總數,這個會預設執行一個count的語句,是以性能較低。

2 分頁

Slice<UserInfo> findByName(String name, Pageable pageable);

           

傳回結果是Slice,隻查詢結果不關心總數。

3 排序

List<UserInfo> findByName(String name, Sort sort);

           

隻需要排序的時候可以這樣操作,添加一個Sort參數即可。

4 排序和分頁

List<UserInfo> findByName(String name, Pageable pageable);

           

這種情況下将隻傳回限制查詢的結果,而其他的資訊不做傳回。

當在service層使用的時候,可以如下操作

//查詢name是Luke的第一頁,每頁10個資訊,并傳回一共有多少頁
Page<UserInfo> userList = userRepository.findByName("Luke",PageRequest.of(1,10));
//查詢name是Luke的第一頁的10條資料
Slice<UserInfo> userList = userRepository.findByName("Luke",PageRequest.of(1,10));
//查詢name是Luke的資料,并按照age的逆序排列
List<UserInfo> userList = userRepository.findByName("Luke",new Sort(Sort.Direction.DESC,"age"));
//查詢name是Luke的資料,取第一頁的10條資料,并按照age的逆序排列
List<UserInfo> userList = userRepository.findByName("Luke",PageRequest.of(1,10,Sort.Direction.DESC,"age"));

           

5 限制查詢結果:Fist和Top

當隻想取前幾天資料的時候,可以使用First和Top關鍵字。

舉例說明

//按照name字段順序排列,取第一個值
UserInfo findFirstByOrderByNameAsc();
//根據Id逆序排列并取第一個值
UserInfo findTopByOrderByIdDesc();
//排序後取前10個
List<UserInfo> findFirst10ByAge(Integer age,Sort sort);

           

值得注意的是:

  • 查詢的時候可以在top和first後邊跟數字表示需要多少個值。
  • 若是沒有數字,預設就是1
  • 若是由Pageable參數,則以Top和First後邊的數字為準
  • 也支援Distinct關鍵字

6 @NotNull @NonNullApi和@Nullable

@NotNull

用于不能為空的參數或者傳回值

@NonNullApi

可以定義在包上,用于表示傳回值的預設行為是不接受空值的

@Nullable

用于可以為空的參數或者傳回值

以下代碼表示,表示參數和傳回值都可以是空了。

@Nullable
UserInfo findByName(@Nullable String n