1、前言
Spring Data JPA 是 Spring 基于 ORM 框架、JPA 規范的基礎上封裝的一套 JPA 應用框架,底層使用了 Hibernate 的 JPA 技術實作,可使開發者用極簡的代碼即可實作對資料的訪問和操作,它提供了包括增、刪、改、查等在內的常用功能,易于擴展,極大提高開發效率,
Spring Data Common 是 Spring Data 所有模塊的公共部分,該專案提供了基于 Spring 的共享基礎設施,它提供了基于 repository 介面以 DB 操作的一些封裝,以及一個堅持在 Java 物體類上標注元資料的模型,
Spring Data 不僅對傳統的資料庫訪問技術如 JDBC、Hibernate、JDO、TopLick、JPA、MyBatis 做了很好的支持和擴展、抽象、提供方便的操作方法,還對 MongoDb、KeyValue、Redis、LDAP、Cassandra 等非關系資料的 NoSQL 做了不同的實作版本,方便我們開發者觸類旁通,
2、Spring Data JPA 優勢
-
使用廣泛,大廠必備,借助于spring boot廣泛受眾人群,與 Spring Boot 天然集成的 Spring Data JPA 也逐漸走進了 Java 開發者的視野,JPA 可以使團隊在框架約定下進行開發,幾乎很難寫出有性能瓶頸的 SQL,
-
提升開發效率,剛開始時學習語法(比如方法名、SQL 邏輯)要花點時間,一旦完成系統化的學習后,你可以熟練使用 JPA,那么半小時甚至幾分鐘就可以寫好查詢方法了;再配合測驗用例,你的開發質量也會明顯提高很多,
-
提升技術水平,Spring Data 對資料庫進行了封裝,統一了關系型資料庫和非關系型資料的介面、公共的部分,你會發現,一旦掌握了Spring Data JPA框架后,你可以輕易實作對
Redis、MongoDB等NoSQL的操作,他們底層依賴了統一的Spring Data Common,
Spring Data和JPA的結構關系:
![]()

3、專案集成
外部依賴:
Spring Boot 已經為 JPA 封裝了starter組件,只需在 pom.xml 檔案中添加jar版本依賴即可:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
Spring Boot Starter Data JPA 依賴 Spring Data JPA;而 Spring Data JPA 依賴 Spring Data Commons,
組態檔:
在組態檔 application.yaml 中配置 JPA 的相關引數,具體內容如下:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/ds0?characterEncoding=utf-8
username: root
password: 111111
# Hikari config
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 10
maximum-pool-size: 200
idle-timeout: 60000
pool-name: MarketingHikariCP
max-lifetime: 1800000
connection-timeout: 2000
connection-test-query: select 1
jpa:
show-sql: true #在控制臺列印 sql 陳述句
資料庫連接用的是 JDBC,連接池用的是 HikariCP,強依賴 Hibernate;
工程結構如圖所示:

定義物體物件:
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@JsonIgnoreProperties(value = {"hibernateLazyInitializer"})
public class User {
@Id // @Id注解指明這個屬性映射為資料庫的主鍵,
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
// 名稱
private String userName;
// 年齡
private Integer age;
// 地址
private String address;
}
注解說明:
-
@Entity 是一個類注解,用來注解該類是一個物體類用來進行和資料庫中的表建立關聯關系,首次啟動專案的時候,默認會在資料中生成一個同物體類相同名字的表(table),也可以通過注解中的 name 屬性來修改表(table)名稱, 如@Entity(name=“user”) , 這樣資料庫中表的名稱則是 user ,該注解十分重要,如果沒有該注解首次啟動專案的時候你會發現資料庫沒有生成對應的表,
-
@Table 注解也是一個類注解,該注解可以用來修改表的名字,該注解完全可以忽略掉不用,@Entity 注解已具備該注解的功能,
-
@Id 類的屬性注解,該注解表明該屬性欄位是一個主鍵,該屬性必須具備,不可缺少,
-
@GeneratedValue 該注解通常和 @Id 主鍵注解一起使用,用來定義主鍵的呈現形式,該注解通常有多種使用策略,總結如下:
-
@GeneratedValue(strategy= GenerationType.IDENTITY) 該注解由資料庫自動生成,主鍵自增型,在 mysql 資料庫中使用最頻繁,oracle 不支持,
-
@GeneratedValue(strategy= GenerationType.AUTO) 主鍵由程式控制,默認的主鍵生成策略,oracle 默認是序列化的方式,mysql 默認是主鍵自增的方式,
-
@GeneratedValue(strategy= GenerationType.SEQUENCE) 根據底層資料庫的序列來生成主鍵,條件是資料庫支持序列,Oracle支持,Mysql不支持,
-
@GeneratedValue(strategy= GenerationType.TABLE) 使用一個特定的資料庫表格來保存主鍵,較少使用,
-
@Column 是一個類的屬性注解,該注解可以定義一個欄位映射到資料庫屬性的具體特征,比如欄位長度,映射到資料庫時屬性的具體名字等,
-
@Transient 是一個屬性注解,該注解標注的欄位不會被映射到資料庫當中,
資料訪問層 UserRepository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByUserName(String userName);
List<User> findByUserNameAndAddress(String userName, String address);
// 使用 @Query查詢,引數按照名稱系結
@Query("select u from User u where u.userName= :userName and u.address= :address")
List<User> queryByUserNameAndAddress(@Param("userName") String userName, @Param("address") String address);
}
層次結構類圖:

UserRepository 介面繼承 JpaRepository,JpaRepository繼承了介面PagingAndSortingRepository和QueryByExampleExecutor,而PagingAndSortingRepository又繼承CrudRepository,
-
CrudRepository:提供了常用的存盤層的增、刪、改、查 操作方法
-
PagingAndSortingRepository:主要用于分頁查詢、排序查詢
-
JpaRepository:上面介面是為了兼容 NoSQL 而進行的一些抽象封裝,從 JpaRepository 開始是對關系型資料庫進行抽象封裝,JpaRepository 里面重點新增了批量洗掉,優化了批量洗掉的性能,類似于之前 SQL 的 batch 操作,并不是像上面的 deleteAll 來 for 回圈洗掉,其中 flush() 和 saveAndFlush() 提供了手動重繪 session,把物件的值立即更新到資料庫里面的機制,
除了使用繼承系統提供的擴展介面類外,還可以采用約定規則方式,
自定義的簡單查詢就是根據方法名來自動生成SQL,具體是方法名以 findBy、existsBy、countBy、deleteBy 開頭,后面跟具體的條件,舉幾個例子:
| 關鍵字 | 方法示例 | JPQL snippet |
|---|---|---|
| And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
| Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
| Is, Equals | findByFirstname,findByFirstnameIs,findByFirstnameEquals | … where x.firstname = ?1 |
| Between | findByStartDateBetween | … where x.startDate between ?1 and ?2 |
| LessThan | findByAgeLessThan | … where x.age < ?1 |
| LessThanEqual | findByAgeLessThanEqual | … where x.age <= ?1 |
| GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
| GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ?1 |
| After | findByStartDateAfter | … where x.startDate > ?1 |
| Before | findByStartDateBefore | … where x.startDate < ?1 |
| IsNull, Null | findByAge(Is)Null | … where x.age is null |
| IsNotNull, NotNull | findByAge(Is)NotNull | … where x.age not null |
| Like | findByFirstnameLike | … where x.firstname like ?1 |
| NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
| StartingWith | findByFirstnameStartingWith | … where x.firstname like ?1 (parameter bound with appended %) |
| EndingWith | findByFirstnameEndingWith | … where x.firstname like ?1 (parameter bound with prepended %) |
| Containing | findByFirstnameContaining | … where x.firstname like ?1 (parameter bound wrapped in %) |
| OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
| Not | findByLastnameNot | … where x.lastname <> ?1 |
| In | findByAgeIn(Collection ages) | … where x.age in ?1 |
| NotIn | findByAgeNotIn(Collection ages) | … where x.age not in ?1 |
| True | findByActiveTrue() | … where x.active = true |
| False | findByActiveFalse() | … where x.active = false |
| IgnoreCase | findByFirstnameIgnoreCase | … where UPPER(x.firstame) = UPPER(?1) |
Spring Data JPA 已經幫我們實作了分頁,在查詢的方法中,需要傳入引數PageRequest,當查詢中有多個引數的時候PageRequest建議做為最后一個引數傳入,PageRequest是 spring 封裝的分頁實作類,使用的時候需要傳入頁數、每頁條數和排序規則
@RequestMapping("/page")
public Page<User> page(@RequestParam("pageNo") int pageNo, @RequestParam("pageSize") int pageSize) {
Page<User> pageUser = userRepository.findAll(new PageRequest(pageNo, pageSize));
return pageUser;
}
Spring data 大部分的 SQL 都可以根據方法名定義的方式來實作,但是有些復雜業務場景需要使用自定義的 SQL 來查詢,spring data 也是支持的,
@Query("select u from User u where u.userName= :userName and u.address= :address")
List<User> queryByUserNameAndAddress(@Param("userName") String userName, @Param("address") String address);
4、專案原始碼地址
https://github.com/aalansehaiyang/spring-boot-bulking
模塊:spring-boot-bulking-data-jpa
往期推薦
-
Spring Boot 集成 ElasticSearch,實作高性能搜索
-
框架擴展:注解 RPC Consumer屬性動態注入
-
淘寶訂單自動確認識訓的N種實作,秒殺面試官
-
深入剖析優惠券核心架構設計
-
某生鮮電商平臺的庫存扣減方案
-
被嚇了一跳,算一算優惠券的利潤賬!
-
如何設計一個高性能的秒殺系統
-
如何通過Binlog來實作不同系統間資料同步
-
電商優惠券如何設計?
-
單臺 MySQL 支撐不了這么多的并發請求,我們該怎么辦?
-
聊聊電商促銷業務
-
DDD是如何解決復雜業務擴展問題?
-
線上服務的FGC問題排查,看這篇就夠了!
-
springboot + aop + Lua分布式限流的最佳實踐
我們熱衷于收集高并發、系統架構、微服務、訊息中間件、 RPC框架、高性能快取、搜索、分布式資料框架、分布式協同服務、分布式配置中心、中臺架構、領域驅動設計、系統監控、系統穩定性等技術知識,

歡迎你掃 ↑↑↑ 二維碼加入我們,在群里,深入交流、共同成長、共同進步! 書山有路勤為徑, 學海無涯苦作舟,
關注公眾號,后臺回復 “中臺”,下載PDF學習資料
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/258700.html
標籤:其他
上一篇:網路編程3
下一篇:簡單的SSM整合專案。
