SpringBoot - 第十四章 | Spring-data-jpa訪問資料庫
在前面的文章中 第十三章 - SpringBoot JdbcTemplate訪問資料庫 介紹如何使用JdbcTemplate的基本訪問資料庫。
而在實際的專案開發中,最基本的資料庫操作不外乎「CRUD」,而這些操作除了資料表名稱和結構不同外,其語法都是類似的,開發人員需要寫大量類似而枯燥的語法來完成業務邏輯。
為了解決這些大量枯燥的資料操作語法,我們可以使用ORM框架,比如:Hibernate。通過整合Hibernate之後,我們以操作Java實體的方式最終將資料改變映射到資料庫表中。
為了解決抽象各個Java實體基本的「CRUD」操作,我們通常會以泛型的方式封裝一個模板Dao來進行抽像簡化,但是這樣依然不是很方便,我們需要針對每個實體編寫一個繼承自泛型模板Dao的接口,再編寫該接口的實現。雖然一些基礎的資料訪問已經可以得到很好的複用,但是在代碼結構上針對每個實體都會有一堆Dao的接口和實現。
由於模板Dao的實現,使得這些具體實體的Dao層已經變的非常”薄”,有一些具體實體的Dao實現可能完全就是對模板Dao的簡單代理,並且往往這樣的實現類可能會出現在很多實體上。 Spring-data-jpa的出現正可以讓這樣一個已經很”薄”的資料訪問層變成只是一層接口的編寫方式。
「CRUD」表示:(Create)、讀取(Read)、更新(Update)、刪除(Delete)
簡單介紹
JPA是Java Persistence API的簡寫,是官方提出的一種ORM規範!
JPA規範,都在包路徑:javax.persistence.*下,像一些常用的如:@Entity、@Id及@Transient都在此路徑下。這些也是一些現在市面上常用的ORM一些約定俗成的註解了。
Spring Data JPA是Spring基於Hibernate開發的一個JPA框架。可以極大的簡化JPA的寫法,可以在幾乎不用寫具體代碼的情況下,實現對資料的訪問和操作。除了「CRUD」外,還包括如分頁、排序等一些常用的功能。
Spring Data JPA 接口和核心概念
接口 | 說明 |
---|---|
Repository | 最頂層的接口,是一個空的接口,目的是為了統一所有Repository的類型,且能讓組件掃描的時候自動識別 |
CrudRepository | 是Repository的子接口,提供CRUD的功能 |
PagingAndSortingRepository | 是CrudRepository的子接口,添加分頁和排序的功能 |
JpaRepository | 是PagingAndSortingRepository的子接口,增加了一些實用的功能,比如:批量操3作等 |
JpaSpecificationExecutor | 用來做負責查詢的接口 |
Specification | 是Spring Data JPA提供的一個查詢規範,要做複雜的查詢,只需圍繞這個規範來設置查詢條件即可 |
Spring Data JPA 方法命名效果
可以通過方法命名規則進行相關資料庫操作,這個確實可以減少很多代碼
關鍵字 | 方法命名 | sql where字句 |
---|---|---|
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(?) |
這個方式確實減少很多程式的撰寫,但是條件一多,方法名稱就會變很長
使用範例
由於Spring-data-jpa依賴於Hibernate。如果你對Hibernate有一定了解,下面內容可以毫不費力的看懂並上手使用Spring-data-jpa。如果你還是Hibernate新手,你可以先按如下方式入門,再建議回頭學習一下Hibernate以幫助這部分的理解和進一步使用。
資料庫範例
這邊用Customer來做範例
1 | DROP TABLE IF EXISTS `customer`; |
相關配置
加入pom的依賴
1
2
3
4<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>src/main/resources/application.properties中配置資料源訊息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 資料源配置
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# 顯示SQL語法
spring.jpa.show-sql=true
# format SQL語法
spring.jpa.properties.hibernate.format_sql=true
# 顯示SQL語法的查詢條件的值
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
# 自動建立(此參數請小心使用)
#spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop
spring.jpa.properties.hibernate.hbm2ddl.auto是hibernate的配置屬性,其主要作用是:自動建立、更新、驗證資料庫表結構。該參數的幾種配置如下:
create:每次加載hibernate時都會刪除上一次的生成的表,然後根據你的model類再重新來生成新表,哪怕兩次沒有任何改變也要這樣執行,這就是導致資料庫表資料丟失的一個重要原因。
create-drop:每次加載hibernate時根據model類生成表,但是sessionFactory一關閉,表就自動刪除。
update:最常用的屬性,第一次加載hibernate時根據model類會自動建立起表的結構(前提是先建立好資料庫),以後加載hibernate時根據model類自動更新表結構,即使表結構改變了但表中的行仍然存在不會刪除以前的行。要注意的是當部署到伺服器後,表結構是不會被馬上建立起來的,是要等應用第一次運行起來後才會。
validate:每次加載hibernate時,驗證建立資料庫表結構,只會和資料庫中的表進行比較,不會建立新表,但是會插入新值。
注意:spring.jpa.properties.hibernate.hbm2ddl.auto,於程式啟動會時自動先將你的Table Drop在自動建立與Model資料定義的欄位名稱一模一樣的Table
建立實體 (Entity)
實體類上加入@EntityListeners(AuditingEntityListener.class),啟動類上加入註解@EnableJpaAuditing,這樣就實現了類似公共字段自動填充功能了@CreatedDate、@LastModifiedDate、@CreatedBy、@LastModifiedBy。
@Entity:告訴Spring這是資料模型層的宣告
@Table:Table的name對應到資料庫中的資料表名稱
@Id:是此資料表的Primary Key
@GeneratedValue:告訴此Column的生成方式。
– GenerationType.AUTO 讓容器來自動產生
– GenerationType.IDENTITY 讓資料庫自己維護@Column:對應到Table的欄位中的欄位名稱
建立資料訪問對象 (Dao)
注意:這裡繼承了JpaRepository。另外要實現分頁功能,可以繼承PagingAndSortingRepository,佔位符為:?+具體的參數索引值;所以按自己需要做繼承選擇,CrudRepository、PagingAndSortingRepository、JpaRepository等。
編輯啟動類 (Application)
單元測試
以上三個Entity、Dao、Application處理好後,這邊就可以先進行基本的測試。
測試結果
到這邊基本上JPA的使用已經實作完畢了,而下面的部分是希望結合Service、Controller來做測試和應用,讓我們可以做個比較完整範例。
一般來說Controller多數都是處理頁面的部分,而Service就是在處理業務邏輯的部分,Dao就是單純對資料庫的操作。
建立邏輯介面層 (Service interface)
建立邏輯實作層 (Service implement)
建立Controller
Postman測試
- 新增用戶
- 找尋用戶(ById)
- 刪除用戶(ById)
- 找尋用戶(ByNameAndAge)
註:以上參考了
程序猿DD-翟永超 的 Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅 文章。
oKong 的 SpringBoot | 第三十章:Spring-data-jpa的集成和使用 文章。
Spring Data JPA findOne()更改为Optional如何使用这个?
Day12-Spring Boot-什麼是Spring Data JPA