Spring data簡述
•Spring Data : Spring 的一個子項目。用于簡化資料庫通路,支援NoSQL 和關系資料存儲。其主要目标是使資料庫的通路變得友善快捷。
•SpringData項目所支援 NoSQL 存儲:
–MongoDB(文檔資料庫)
–Neo4j(圖形資料庫)
–Redis(鍵/值存儲)
–Hbase(列族資料庫)
•SpringData項目所支援的關系資料存儲技術:
–JDBC
–JPA
•JPA Spring Data : 緻力于減少資料通路層 (DAO) 的開發量. 開發者唯一要做的,就隻是聲明持久層的接口,其他都交給 Spring Data JPA 來幫你完成!
•架構怎麼可能代替開發者實作業務邏輯呢?比如:當有一個 UserDao.findUserById() 這樣一個方法聲明,大緻應該能判斷出這是根據給定條件的 ID 查詢出滿足條件的User 對象。Spring Data JPA 做的便是規範方法的名字,根據符合規範的名字來确定方法需要實作什麼樣的邏輯。
Spring Data Jpa HelloWorld
•使 Spring Data JPA 進行持久層開發需要的四個步驟:
–配置Spring 整合JPA
–在 Spring 配置檔案中配置 Spring Data,讓 Spring 為聲明的接口建立代理對象。配置了 <</span>jpa:repositories> 後,Spring 初始化容器時将會掃描 base-package 指定的包目錄及其子目錄,為繼承 Repository 或其子接口的接口建立代理對象,并将代理對象注冊為 Spring Bean,業務層便可以通過 Spring 自動封裝的特性來直接使用該對象。
–聲明持久層的接口,該接口繼承 Repository,Repository 是一個标記型接口,它不包含任何方法,如必要,Spring Data 可實作 Repository 其他子接口,其中定義了一些常用的增删改查,以及分頁相關的方法。
–在接口中聲明需要的方法。Spring Data 将根據給定的政策(具體政策稍後講解)來為其生成實作代碼。
環境搭建
•同時下載下傳 Spring Data Commons 和 Spring Data JPA 兩個釋出包:
–Commons 是 Spring Data 的基礎包
–并把相關的依賴 JAR 檔案加入到 CLASSPATH 中
•在 Spring 的配置檔案中配置 Spring Data
代碼示範:
Repository 接口
•Repository 接口是 Spring Data 的一個核心接口,它不提供任何方法,開發者需要在自己定義的接口中聲明需要的方法
public interface RepositorySerializable> { }
•Spring Data可以讓我們隻定義接口,隻要遵循 Spring Data的規範,就無需寫實作類。
•與繼承 Repository 等價的一種方式,就是在持久層接口上使用@RepositoryDefinition 注解,并為其指定 domainClass和 idClass屬性。如下兩種方式是完全等價的
Repository 的子接口
•基礎的 Repository 提供了最基本的資料通路功能,其幾個子接口則擴充了一些功能。它們的繼承關系如下:
–Repository: 僅僅是一個辨別,表明任何繼承它的均為倉庫接口類
–CrudRepository: 繼承 Repository,實作了一組 CRUD 相關的方法
–PagingAndSortingRepository: 繼承 CrudRepository,實作了一組分頁排序相關的方法
–JpaRepository: 繼承 PagingAndSortingRepository,實作一組 JPA 規範相關的方法
–自定義的 XxxxRepository 需要繼承 JpaRepository,這樣的XxxxRepository接口就具備了通用的資料通路控制層的能力。
–JpaSpecificationExecutor: 不屬于Repository體系,實作一組 JPACriteria 查詢相關的方法
SpringData 方法定義規範
•簡單條件查詢: 查詢某一個實體類或者集合
•按照 Spring Data 的規範,查詢方法以 find | read | get 開頭,
涉及條件查詢時,條件的屬性用條件關鍵字連接配接,要注意的是:條件屬性以首字母大寫。
•例如:定義一個 Entity 實體類
class User{
private String firstName;
private String lastName;
}
使用And條件連接配接時,應這樣寫:
findByLastNameAndFirstName(String lastName,StringfirstName);
條件的屬性名稱與個數要與參數的位置與個數一一對應
支援的關鍵字
•直接在接口中定義查詢方法,如果是符合規範的,可以不用寫實作,目前支援的關鍵字寫法如下:
查詢方法解析流程
•假如建立如下的查詢:findByUserDepUuid(),架構在解析該方法時,首先剔除findBy,然後對剩下的屬性進行解析,假設查詢實體為Doc
–先判斷 userDepUuid(根據 POJO 規範,首字母變為小寫)是否為查詢實體的一個屬性,如果是,則表示根據該屬性進行查詢;如果沒有該屬性,繼續第二步;
–從右往左截取第一個大寫字母開頭的字元串(此處為Uuid),然後檢查剩下的字元串是否為查詢實體的一個屬性,如果是,則表示根據該屬性進行查詢;如果沒有該屬性,則重複第二步,繼續從右往左截取;最後假設user 為查詢實體的一個屬性;
–接着處理剩下部分(DepUuid),先判斷 user 所對應的類型是否有depUuid屬性,如果有,則表示該方法最終是根據 “Doc.user.depUuid” 的取值進行查詢;否則繼續按照步驟 2 的規則從右往左截取,最終表示根據 “Doc.user.dep.uuid” 的值進行查詢。
–可能會存在一種特殊情況,比如 Doc包含一個 user 的屬性,也有一個userDep屬性,此時會存在混淆。可以明确在屬性之間加上 "_" 以顯式表達意圖,比如 "findByUser_DepUuid()" 或者"findByUserDep_uuid()"
•特殊的參數: 還可以直接在方法的參數上加入分頁或排序的參數,比如:
–Page<</span>UserModel> findByName(String name, Pageablepageable);
–List<</span>UserModel> findByName(String name, Sort sort);
使用 @Query 注解
•這種查詢可以聲明在 Repository 方法中,擺脫像命名查詢那樣的限制,将查詢直接在相應的接口方法中聲明,結構更為清晰,這是 Spring data 的特有實作。
索引參數與命名參數
•索引參數如下所示,索引值從1開始,查詢中 ”?X” 個數需要與方法定義的參數個數相一緻,并且順序也要一緻
•
•
•命名參數(推薦使用這種方式):可以定義好參數名,指派時采用@Param("參數名"),而不用管順序。
•如果是 @Query 中有 LIKE 關鍵字,後面的參數需要前面或者後面加 %,這樣在傳遞參數值的時候就可以不加 %:
–@Query("select o from UserModelo where o.name like ?1%")
public List<</span>UserModel> findByUuidOrAge(String name);
–@Query("select o from UserModel o where o.name like %?1")
public List<</span>UserModel> findByUuidOrAge(String name);
–@Query("select o from UserModelo where o.name like %?1%")
public List<</span>UserModel> findByUuidOrAge(String name);
•還可以使用@Query來指定本地查詢,隻要設定nativeQuery為true,比如:
–@Query(value="select * from tbl_userwhere name like %?1" ,nativeQuery=true)
public List<</span>UserModel> findByUuidOrAge(String name);
@Modifying 注解和事務
•@Query 與 @Modifying 這兩個 annotation一起聲明,可定義個性化更新操作,例如隻涉及某些字段更新時最為常用,示例如下:
•
•
•
•注意:
–方法的傳回值應該是 int,表示更新語句所影響的行數
–在調用的地方必須加事務,沒有事務不能正常執行
事務
•Spring Data 提供了預設的事務處理方式,即所有的查詢均聲明為隻讀事務。
•對于自定義的方法,如需改變 Spring Data 提供的事務預設方式,可以在方法上注解 @Transactional 聲明
•進行多個 Repository 操作時,也應該使它們在同一個事務中處理,按照分層架構的思想,這部分屬于業務邏輯層,是以,需要在 Service 層實作對多個Repository 的調用,并在相應的方法上聲明事務。
CrudRepository接口
•CrudRepository接口提供了最基本的對實體類的添删改查操作