1. 程式人生 > 其它 >JPA的Repository詳解

JPA的Repository詳解

JPA的Repository詳解

Spring Data JPA

Spring Data是Spring提供的操作資料的框架,Spring Data JPA是Spring Data的一個模組,通過Spring data 基於jpa標準操作資料的模組。
Spring Data的核心能力,就是基於JPA操作資料,並且可以簡化操作持久層的程式碼。
它使用一個叫作Repository的介面類為基礎,它被定義為訪問底層資料模型的超級介面。而對於某種具體的資料訪問操作,則在其子介面中定義。
Spring Data可以讓我們只定義介面,只要遵循spring data的規範,就無需寫實現類,不用寫sql語句直接查詢資料。

Repository

  • Repository
    提供了findBy + 屬性 方法
    • CrudRepository
      繼承了Repository 提供了對資料的增刪改查
      • PagingAndSortRepository:
        繼承了CrudRepository 提供了對資料的分頁和排序,缺點是隻能對所有的資料進行分頁或者排序,不能做條件判斷
        • JpaRepository: 繼承了PagingAndSortRepository
          開發中經常使用的介面,主要繼承了PagingAndSortRepository,對返回值型別做了適配
  • JpaSpecificationExecutor
    提供多條件查詢

CrudRepository

CrudRepository繼承Repository,添加了一組對資料的增刪改查的方法

PagingAndSortingRepository

PagingAndSortingRepository繼承CrudRepository,添加了一組分頁排序相關的方法

JpaRepository

JpaRepository繼承PagingAndSortingRepository,添加了一組JPA規範相關的方法。對繼承父介面中方法的返回值進行了適配,因為在父類介面中通常都返回迭代器,需要我們自己進行強制型別轉化。而在JpaRepository中,直接返回了List。
開發中最常用JpaRepository


JpaSpecificationExecutor

這個介面比較特殊,單獨存在,沒有繼承以上介面。主要提供了多條件查詢的支援,並且可以在查詢中新增分頁和排序。因為這個介面單獨存在,因此需要配合以上說的介面使用。

JpaRepository查詢功能

Jpa方法命名規則

JpaRepository支援介面規範方法名查詢。意思是如果在介面中定義的查詢方法符合它的命名規則,就可以不用寫實現,目前支援的關鍵字如下。

Keyword Sample JPQL snippet
And findByNameAndPwd where name= ? and pwd =?
Or findByNameOrSex where name= ? or sex=?
Is,Equals findById,findByIdEquals where id= ?
Between findByIdBetween where id between ? and ?
LessThan findByIdLessThan where id < ?
LessThanEquals findByIdLessThanEquals where id <= ?
GreaterThan findByIdGreaterThan where id > ?
GreaterThanEquals findByIdGreaterThanEquals where id > = ?
After findByIdAfter where id > ?
Before findByIdBefore where id < ?
IsNull findByNameIsNull where name is null
isNotNull,NotNull findByNameNotNull where name is not null
Like findByNameLike where name like ?
NotLike findByNameNotLike where name not like ?
StartingWith findByNameStartingWith where name like ‘?%’
EndingWith findByNameEndingWith where name like ‘%?’
Containing findByNameContaining where name like ‘%?%’
OrderBy findByIdOrderByXDesc where id=? order by x desc
Not findByNameNot where name <> ?
In findByIdIn(Collection<?> c) where id in (?)
NotIn findByIdNotIn(Collection<?> c) where id not in (?)
True findByAaaTue where aaa = true
False findByAaaFalse where aaa = false
IgnoreCase findByNameIgnoreCase where UPPER(name)=UPPER(?)
top findTop10 top 10/where ROWNUM <=10

使用方法

使用時自定義介面繼承JpaRepository,傳入泛型,第一個引數為要操作的實體類,第二個引數為該實體類的主鍵型別

public interface SpuRepository extends JpaRepository<Spu, Long> {
    Spu findOneById(Long id);
Page<span class="token generics function"><span class="token punctuation">&lt;</span>Spu<span class="token punctuation">&gt;</span></span> <span class="token function">findByCategoryIdOrderByCreateTimeDesc</span><span class="token punctuation">(</span>Long cid<span class="token punctuation">,</span> Pageable pageable<span class="token punctuation">)</span><span class="token punctuation">;</span>

Page<span class="token generics function"><span class="token punctuation">&lt;</span>Spu<span class="token punctuation">&gt;</span></span> <span class="token function">findByRootCategoryIdOrderByCreateTime</span><span class="token punctuation">(</span>Long cid<span class="token punctuation">,</span> Pageable pageable<span class="token punctuation">)</span><span class="token punctuation">;</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

解析過程

1. Spring Data JPA框架在進行方法名解析時,會先把方法名多餘的字首擷取掉,比如find,findBy,read,readBy,get,getBy,然後對剩下的部分進行解析。
2. 假設建立如下查詢findByCategoryId(),框架在解析該方法時,首先剔除findBy,然後對剩下的屬性進行解析,假設查詢實體為Spu

(1)先判斷categoryId(根據POJO 規範,首字母變為小寫)是否為查詢實體的一個屬性,如果是,則表示根據該屬性進行查詢;如果沒有該屬性,繼續第二步;

(2)從右往左擷取第一個大寫字母開頭的字串此處為Id),然後檢查剩下的字串是否為查詢實體的一個屬性,如果是,則表示根據該屬性進行查詢;
如果沒有該屬性,則重複第二步,繼續從右往左擷取;最後假設user為查詢實體的一個屬性;

(3)接著處理剩下部分(CategoryId),先判斷使用者所對應的型別是否有categoryId屬性,如果有,則表示該方法最終是根據"Spu.categoryId"的取值進行查詢;
否則繼續按照步驟2的規則從右往左擷取。

(4)可能會存在一種特殊情況,比如Spu包含一個categoryId 的屬性,也有一個 rootCategoryId屬

性,此時會存在混淆。可以明確在屬性之間加上"_" 以顯式表達意圖,比如

"findByRoot_CategoryId()"

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3. 特殊引數
可以直接在方法的引數上加入分頁或排序的引數,比如:

Page<Spu> findByCategoryId(Long cid, Pageable pageable);

List<Spu> findByCategoryId(Long cid, Sort sort);

  • 1
  • 2
  • 3

4. JPA的@NamedQueries

(1)1:在實體類上使用@NamedQuery
@NamedQuery(name = "Spu.findByRootCategoryId",query = "select s from Spu s where s.rootCategoryId >= ?1")
(2)在自己實現的DAO的Repository接口裡面定義一個同名的方法,示例如下:
public List<Spu> findByRootCategoryId(Long rootCategoryId);
(3)然後Spring會先找是否有同名的NamedQuery,如果有,那麼就不會按照介面定義的方法來解析。
  • 1
  • 2
  • 3
  • 4
  • 5

5. 使用@Query
在方法上標註@Query來指定本地查詢
引數nativeQuery預設為false,nativeQuery=false時,value引數寫的是JPQL,JPQL是用來操作model物件的

@Query(value="select s from Spu s where s.title like %?1" )
public List<Spu> findByTitle(String title);
  • 1
  • 2

nativeQuery=true時,value引數寫的是原生sql

@Query(value="select * from spu s where s.title like %?1",nativeQuery=true )
public List<Spu> findByTitle(String title);
  • 1
  • 2

6. 使用@Param命名化引數

    @Query(value = "select s from Spu s where s.title in (:titles)")
    List<Spu> findByTitle(@Param("titles") List<String> titles);
  • 1
  • 2

參考文章:
JpaRepository資料層
Spring Data JPA 提供的各種Repository介面
spring data jpa方法命名規則
一步一步學SpringDataJpa——JpaRepository查詢功能

https://blog.csdn.net/xfx_1994/article/details/104921234