序言
Spring Data JPA
作為Spring Data
中對於關係型資料庫支援的一種框架技術,屬於ORM
的一種,通過得當的使用,可以大大簡化開發過程中對於資料操作的複雜度。本文件隸屬於《
Spring Data JPA
用法與技能探究》系列的第一篇。本系列文件規劃對Spring Data JPA
進行全方位的使用介紹,一共分為5篇文件,如果感興趣,歡迎關注交流。《Spring Data JPA用法與技能探究》系列涵蓋內容:
- 開篇介紹 —— 《JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文帶你釐清箇中曲直,給你個選擇SpringDataJPA的理由!》
- 快速上手 —— 《SpringBoot整合JPA介紹》
- 深度進階 —— 《JPA核心型別與用法介紹》
- 可靠保障 —— 《聊一聊資料庫的事務,以及Spring體系下對事務的使用》
- 周邊擴充套件 —— 《JPA開發輔助效率提升方案介紹》
本章節主要對Spring Data JPA的整體情況以及與其相關的一些概念進行一個簡單的介紹。
在具體介紹Spring Data JPA之前,我們可以先來思考一個問題: 在JAVA中,如果需要操作DB,應該怎麼做?
很多人可能首先想到的就是整合一些框架然後去操作就行了、比如mybatis、Hibernate框架之類的。
當然,也可能會有人想起JDBC。
再往深入想一下:
- JAVA裡面的寫的一段DB操作邏輯,是如何一步步被傳遞到DB中執行了的呢?
- 為什麼JAVA裡面可以去對接不同產商的DB產品?
- 為什麼有JDBC、還會有各種mybatis或者諸如Hibernate等ORM框架呢?
- 這些JDBC、JPA、ORM、Hibernate等等相互之間啥關係?
- 除了MyBatis、Hibernate等習以為常的內容,是否還有其他操作DB的方案呢?
- ...
帶著這些問題,我們接下來一步步的進行探討,先樹立對Spring Data JPA的正確印象。
1. 需要釐清的若干概念
1.1. JDBC
談到JAVA運算元據庫相關的概念,JDBC是繞不過去的一個概念。
先來介紹下JDBC究竟是個什麼概念。
JDBC(Java DataBase Connectivity),是java連線資料庫操作的原生介面。
JDBC對Java程式設計師而言是API,為資料庫訪問提供標準的介面。由各個資料庫廠商及第三方中介軟體廠商依照JDBC規範為資料庫的連線提供的標準方法。
概念闡述的可能稍微有點抽象,說的直白點可以這麼理解:各個產商的DB產品很多,JAVA聯合各個DB產商定了個規範,JAVA可以按照規範去編寫程式碼,就可以用相同的操作方法去操作不同產商的DB了。也就是說JDBC是JAVA與各個DB產商之間的一個約定規範、約束的是DB產商的實現規範。
基於JDBC,我們可以在JAVA程式碼中去執行DB操作,如下示意:
package com.txw.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@SuppressWarnings("all") // 註解警告資訊
public class JdbcTest01 {
public static void main(String[] args) throws Exception {
// 1.載入驅動
Class.forName("com.mysql.cj.jdbc.Driver");
// 2 建立和資料庫之間的連線
String username = "testdb";
String password = "testxxxxxx";
String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai";
Connection conn = DriverManager.getConnection(url,username,password);
// 3.準備傳送SQL
String sql = "select * from t_person";
PreparedStatement pstm = conn.prepareStatement(sql);
// 4.執行SQL,接收結果集
ResultSet rs = pstm.executeQuery();
// 5 處理結果集
while(rs.next()){
int personId1 = rs.getInt("person_id");
String personName1 = rs.getString("person_name");
int age1 = rs.getInt("age");
String sex1 = rs.getString("sex");
String mobile1 = rs.getString("mobile");
String address1 = rs.getString("address");
System.out.println("personId="+personId1+",personName="+personName1
+",age="+age1+",sex="+sex1+",mobile="+mobile1+",address="+address1);
}
// 6.釋放資源
rs.close();
pstm.close();
conn.close();
}
}
從上面程式碼示例中可以看出JDBC的幾個操作關鍵環節:
- 根據使用的DB型別不同,載入對應的JdbcDriver
- 連線DB
- 編寫SQL語句
- 傳送到DB中執行,並接收結果返回
- 對結果進行處理解析
- 釋放過程中的連線資源
從演示程式碼裡面,還可以看出,直接基於JDBC進行操作DB的時候,其弊端還是比較明顯的:
- 業務程式碼裡面耦合了字串格式SQL語句,複雜場景維護起來比較麻煩;
- 非結構化的key-value對映方式處理結果,操作過於複雜,且不符合JAVA物件導向的思想;
- 需要關注過程資源的釋放、操作不當容易造成洩露。
也正是由於JDBC上述比較明顯的弊端,純基於JDBC操作DB一般僅用於一些小型簡單的場景,正式大型專案中,往往很少有直接基於JDBC進行編碼開發的,而是藉助一些封裝框架來實現。
1.2. ORM框架
物件-關係對映(Object-Relational Mapping,簡稱ORM)。ORM框架中貫穿著JAVA物件導向程式設計的思想,是物件導向程式設計的優秀代言人。
直白點說,ORM就是將程式碼裡面的JAVA類與DB中的table表進行對映,程式碼中對相關JAVA類的操作,即體現為DB中對相關Table的操作。
ORM框架很好的解決了JDBC存在的一系列問題,簡化了JAVA開發人員的編碼複雜度。
1.3. JPA介紹
JPA
, 即Java Persistence API
的縮寫,也即JAVA
持久化層API,這個並非是一個新的概念,其實在JDK5.x版本中就已經引入的一個概念。其宗旨是為POJO
提供一個基於ORM
的持久化操作的標準規範。
涵蓋幾個方面:
-
一套標準API
在javax.persistence的包下面提供,用來操作實體物件,執行CRUD操作,將開發者從煩瑣的JDBC和SQL程式碼中解脫出來,按照JAVA思路去編寫程式碼操作DB。 -
物件導向操作語言
通過物件導向的思路,避免程式碼與SQL的深度耦合。 -
ORM後設資料對映
ORM,即Object Relation Mapping,物件關係對映。
JAVA應用程式,可以通過JPA規範,利用一些常見的基於JPA規範的框架來實現對DB的操作。而常見的一些ORM框架,比如Hibernate
、EclipseLink
、OpenJPA
等等,其實都是提供了對JPA規範的支援,是JPA規範的具體實現提供者,用於輔助JAVA程式對資料庫資料的操作。
1.4. Spring Data JPA
基於前面介紹,我們瞭解到JPA的基本概念,知曉JPA其實是一個基於ORM的JAVA API規範定義,那麼這裡提及的Spring Data JPA
又是什麼呢?其與JPA
之間的關係又是如何呢?
Spirng Data JPA
是Spring
提供的一套簡化JPA
開發的框架,按照約定好的【方法命名規則】寫DAO
層介面,就可以在不寫介面實現的情況下,實現對資料庫的訪問和操作,同時提供了很多除了CRUD之外的功能,如分頁、排序、複雜查詢等等。
注意
Spring Data JPA不是一個完整JPA規範的實現,它只是一個程式碼抽象層,主要用於減少為各種持久層儲存實現資料訪問層所需的程式碼量。其底層依舊是Hibernate
。
可以把Spring Data JPA
理解為JPA
規範的再次封裝抽象。
1.5. Hibernate
hibernate是一個標準的orm框架,實現jpa介面。
1.6. JDBC,ORM,JPA,Spring Data JPA之間到底啥關係
一個簡單粗暴的理解方式:
- JDBC是JAVA操作最終資料庫的底層介面,JDBC是與各個DB產商之間約定的協議規範,基於這些規範,可在JAVA程式碼中往DB執行SQL操作。
- 因為JDBC負責將SQL語句執行到DB中,屬於相對原始的介面,業務程式碼裡面需要構建拼接出SQL語句,然後基於JDBC去DB中執行對應SQL語句。這樣存在的問題會比較明顯,JAVA程式碼中需要耦合大量的SQL語句、且因為缺少封裝,實際業務編碼使用時會比較繁瑣、維護複雜。
- 為了能夠將程式碼與SQL語句分離開,以一種更符合JAVA物件導向程式設計思維的方式來操作DB,誕生了ORM(Object Relation Mapping, 物件關係對映)概念,ORM將JAVA的Object與DB中的Table進行對映起來,管理Object也等同於對Table的管理與操作,這樣就可以實現沒有SQL的情況下實現對DB的操作。常見的ORM框架有
Hibernate
、EclipseLink
、OpenJPA
等等。 - 為了規範ORM的具體使用,JAVA 5.x開始制定了基於ORM思想的Java持久化層操作API規範,也即JPA(注意,JPA只是一個基於ORM的JAVA API規範,供各個ORM框架提供API時遵循),當前主流ORM框架都是支援JPA規範的。
- Spring框架盛行的時代,為了能夠更好適配,Spring Data JPA誕生, 這個可以理解為對JPA規範的二次封裝(可以這麼理解:Spring Data JPA不是一個完整JPA規範的實現,它只是一個程式碼抽象層,主要用於減少為各種持久層儲存實現資料訪問層所需的程式碼量),其底層使用的依舊是常規ORM框架(Hibernate)。
相互之間的關係詳解,見下圖示意。
2. 選擇Spring Data JPA的理由
2.1. Spring Data JPA的優勢
在介紹Spring Data JPA的優勢前,先看個程式碼例子。
場景:
一張使用者表(UserEntity),資訊如下:
ID | UserName | Department | Role |
---|---|---|---|
1 | Jack | DevDept | Normal |
2 | Tom | DevDept | Admin |
3 | Tony | SaleDept | Normal |
程式碼中實現如下訴求:
(1)獲取所有研發部門的人員:
List<UserEntity> users = userReposity.findAllByDepartment("DevDept");
(2)獲取研發部門的管理員:
List<UserEntity> users = userReposity.findAllByDepartmentAndRole("DevDept", "Admin");
看完上面的例子,一個最直觀的感受是什麼?
簡單!
沒錯,“簡單”就是Spring Data JPA最大的優勢!
對於大部分的常規操作,基於Spring Data JPA,開發人員可以更加專注於業務邏輯的開發,而不用花費太多的精力去關注DB層面的封裝處理以及SQL的編寫維護,甚至在DAO層都不需要去定義介面。
除了簡化開發,JPA還有的另一個比較大的優勢,就是其可移植性比較好,因為其通過JPQL的方式進行操作,與原生SQL之間幾乎沒有耦合,所以可以方便的將底層DB切換到別的型別。
2.2. Spring Data JPA整體實現邏輯
基於前面的介紹,我們可以這樣理解,JAVA業務層呼叫SpringData JPA二次封裝提供的Repository層介面,進而基於JPA標準API進行處理,基於Hibernate提供的JPA具體實現,接著基於JDBC標準API介面,完成與實際DB之間的請求互動。整體的處理邏輯全貌圖如下:
這裡可以看出,JPA、Hibernate、SpringData JPA三者之間的關係:
- JPA(Java Persistence API)是規範,它指明瞭持久化、讀取和管理 Java 物件對映到資料庫表時的規範。
- Hibernate 則是一個 ORM 框架,它實現了 Java 物件到資料庫表的對映。也就是說,Hibernate 提供了 JPA 的一種實現。
- Spring Data JPA 是 Spring Framework 的一部分。它不是 JPA 的實現,而是在 JPA 之上提供更高層次的抽象,可以減少很多模板程式碼。而 Spring Data JAP 的預設實現是 Hibernate,當然也可以其他的 JPA Provider。
2.3. Spring Data JPA還是MyBatis?如何抉擇
提到JPA, 那麼MyBatis絕對是無法迴避的一個內容。的確,作為JAVA持久化層的優秀框架,MyBatis甚至是很多開發人員在專案構建初期腦海中唯一的選型方案。那麼,JPA想要從MyBatis佔領地中分一杯羹,究竟是具有哪方面的優勢呢?
先來了解下MyBatis。
MyBatis是一款優秀的持久層框架,它支援定製化SQL、儲存過程以及高階對映。MyBatis 避免了幾乎全部的JDBC程式碼和手動設定引數以及獲取結果集。MyBatis可使用簡單的XML或註解來配置和對映原生資訊,將介面和Java的POJOs(Plain Old Java Objects,普通的 Java物件)對映成資料庫中的記錄。
優勢:
- MyBatis則是一個可以靈活編寫sql語句
- MyBatis避免了幾乎全部的JDBC程式碼和手動設定引數以及獲取結果集,相比JDBC更方便
MyBatis與JPA的差異點:
- 設計哲學不同,MyBatis偏向於程式導向,JPA則將物件導向發揮到極致;
- MyBatis定製起來更加靈活,支援高度定製化的sql語句,支援任意編寫sql語句;JPA相對更注重對已有高頻簡單操作場景的封裝,簡化開發人員的重複操作,雖然JPA也支援定製SQL語句,但是相比MyBatis靈活度略差。
至此,到底如何在JPA與MyBatis之間抉擇,就比較清晰了:
- 如果你的系統中對DB的操作沒有太多額外的深度定製、對DB的執行效能也不是極度敏感、不需要基於SQL語句做一些深度的優化,大部分場景都是一些基礎CRUD操作,則無疑Spring Data JPA是比較理想的選擇,它將大大降低開發人員在DB操作層面的投入精力。
- 如果你的業務中對DB高階邏輯依賴太深,比如大部分場景都需要額外定製複雜SQL語句來實現,或者系統對效能及其敏感,需要基於Table甚至column維度進行深度優化,或者資料量特別巨大的場景,則相比較而言,MyBatis提供的調優定製靈活性上要更有優勢一些。
綜上分析,其實MyBatis與Spring Data JPA其實沒有一個絕對的維度來評價誰更優一些,具體需要結合自身的實際訴求來選擇。
再看個有意思的資料,此前有人統計過使用百度、谷歌等搜素引擎搜素JPA與Mybatis關鍵字的搜尋熱度與區域的資料,如下所示:
從圖中可以看出,MyBatis在中國地區相對更受歡迎一些,但是在國外JPA的受歡迎度要更高一些。
3. 小結,承上啟下
好啦,本篇內容就介紹到這裡。
通過本篇內容,對JAVA體系中DB操作相關的元件、規範等有了一定初步的瞭解,也大致瞭解了應該如何選擇是使用JPA還是MyBatis選型。
後續幾篇系列文章中,將會一步步的介紹下Spring Data JPA的核心內容與具體專案實現,一步步的揭開JPA的廬山真面目。
如果通過本文介紹,你對JPA也有進一步瞭解的興趣,歡迎關注我的後續系列文件。
如果對本文有自己的見解,或者有任何的疑問或建議,都可以留言,我們一起探討、共同進步。
我是悟道君,聊技術、又不僅僅聊技術~
期待與你一起探討,一起成長為更好的自己。