J.J. Huang   2019-03-28   Spring Boot   瀏覽次數:次  

SpringBoot - 第十四章 | Spring-data-jpa訪問資料庫

📑 目錄
  1. 簡單介紹
    1. Spring Data JPA 接口和核心概念
    2. Spring Data JPA 方法命名效果
  2. 使用範例
    1. 資料庫範例
    2. 相關配置
    3. 建立實體 (Entity)
    4. 建立資料訪問對象 (Dao)
    5. 編輯啟動類 (Application)
    6. 單元測試
    7. 建立邏輯介面層 (Service interface)
    8. 建立邏輯實作層 (Service implement)
    9. 建立Controller
    10. Postman測試

在前面的文章中 第十三章 - 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
2
3
4
5
6
7
8
9
10
11
DROP TABLE IF EXISTS `customer`;
CREATE TABLE `customer` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(64) DEFAULT NULL COMMENT '姓名',
`age` smallint(3) DEFAULT NULL COMMENT '年齡',
`create_by` varchar(50) NOT NULL COMMENT '建立人員',
`create_dt` datetime NOT NULL COMMENT '建立時間',
`modify_by` varchar(50) DEFAULT NULL COMMENT '修改人員',
`modify_dt` datetime DEFAULT NULL COMMENT '修改時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

相關配置

  • 加入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的欄位中的欄位名稱​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​​‌‌​​‌‌​​‌​​​‌‌‌​​​​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​​

更多詳細資料請參考 Spring Data JPA - Reference Documentation

建立資料訪問對象 (Dao)

注意:這裡繼承了JpaRepository。另外要實現分頁功能,可以繼承PagingAndSortingRepository,佔位符為:?+具體的參數索引值;所以按自己需要做繼承選擇,CrudRepository、PagingAndSortingRepository、JpaRepository等。

編輯啟動類 (Application)

單元測試

以上三個Entity、Dao、Application處理好後,這邊就可以先進行基本的測試。​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​​‌‌​​‌‌​​‌​​​‌‌‌​​​​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​​

測試結果

SpringBoot - 第十四章 - 圖 1 (01)

SpringBoot - 第十四章 - 圖 2 (02)​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​​‌‌​​‌‌​​‌​​​‌‌‌​​​​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​​

到這邊基本上JPA的使用已經實作完畢了,而下面的部分是希望結合Service、Controller來做測試和應用,讓我們可以做個比較完整範例。
一般來說Controller多數都是處理頁面的部分,而Service就是在處理業務邏輯的部分,Dao就是單純對資料庫的操作。


建立邏輯介面層 (Service interface)

建立邏輯實作層 (Service implement)

建立Controller

Postman測試

  • 新增用戶

SpringBoot - 第十四章 - 圖 3 (03)

  • 找尋用戶(ById)

SpringBoot - 第十四章 - 圖 4 (04)​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​​‌‌​​‌‌​​‌​​​‌‌‌​​​​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​​

  • 刪除用戶(ById)

SpringBoot - 第十四章 - 圖 5 (05)

  • 找尋用戶(ByNameAndAge)

SpringBoot - 第十四章 - 圖 6 (06)

註:以上參考了
程序猿DD-翟永超Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅 文章。
oKongSpringBoot | 第三十章:Spring-data-jpa的集成和使用 文章。
Spring Data JPA findOne()更改为Optional如何使用这个?
Day12-Spring Boot-什麼是Spring Data JPA​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​​‌‌​​‌‌​​‌​​​‌‌‌​​​​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​​