JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文帶你釐清個中曲直,給你個選擇SpringDataJPA的理由!


序言
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的幾個操作關鍵環節:

  1. 根據使用的DB類型不同,載入對應的JdbcDriver
  2. 連接DB
  3. 編寫SQL語句
  4. 發送到DB中執行,並接收結果返回
  5. 對結果進行處理解析
  6. 釋放過程中的連接資源

從演示程式碼裡面,還可以看出,直接基於JDBC進行操作DB的時候,其弊端還是比較明顯的:

  1. 業務程式碼裡面耦合了字元串格式SQL語句,複雜場景維護起來比較麻煩;
  2. 非結構化的key-value映射方式處理結果,操作過於複雜,且不符合JAVA面向對象的思想;
  3. 需要關注過程資源的釋放、操作不當容易造成泄露。

也正是由於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框架,比如HibernateEclipseLinkOpenJPA等等,其實都是提供了對JPA規範的支援,是JPA規範的具體實現提供者,用於輔助JAVA程式對資料庫數據的操作。

1.4. Spring Data JPA

基於前面介紹,我們了解到JPA的基本概念,知曉JPA其實是一個基於ORM的JAVA API規範定義,那麼這裡提及的Spring Data JPA又是什麼呢?其與JPA之間的關係又是如何呢?

Spirng Data JPASpring提供的一套簡化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之間到底啥關係

一個簡單粗暴的理解方式:

  1. JDBC是JAVA操作最終資料庫的底層介面,JDBC是與各個DB產商之間約定的協議規範,基於這些規範,可在JAVA程式碼中往DB執行SQL操作。
  2. 因為JDBC負責將SQL語句執行到DB中,屬於相對原始的介面,業務程式碼裡面需要構建拼接出SQL語句,然後基於JDBC去DB中執行對應SQL語句。這樣存在的問題會比較明顯,JAVA程式碼中需要耦合大量的SQL語句、且因為缺少封裝,實際業務編碼使用時會比較繁瑣、維護複雜。
  3. 為了能夠將程式碼與SQL語句分離開,以一種更符合JAVA面向對象編程思維的方式來操作DB,誕生了ORM(Object Relation Mapping, 對象關係映射)概念,ORM將JAVA的Object與DB中的Table進行映射起來,管理Object也等同於對Table的管理與操作,這樣就可以實現沒有SQL的情況下實現對DB的操作。常見的ORM框架有HibernateEclipseLinkOpenJPA等等。
  4. 為了規範ORM的具體使用,JAVA 5.x開始制定了基於ORM思想的Java持久化層操作API規範,也即JPA(注意,JPA只是一個基於ORM的JAVA API規範,供各個ORM框架提供API時遵循),當前主流ORM框架都是支援JPA規範的。
  5. 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其實沒有一個絕對的維度來評價誰更優一些,具體需要結合自身的實際訴求來選擇。

再看個有意思的數據,此前有人統計過使用百度、Google等搜素引擎搜素JPA與Mybatis關鍵字的搜索熱度與區域的數據,如下所示:

從圖中可以看出,MyBatis在中國地區相對更受歡迎一些,但是在國外JPA的受歡迎度要更高一些。

3. 小結,承上啟下

好啦,本篇內容就介紹到這裡。

通過本篇內容,對JAVA體系中DB操作相關的組件、規範等有了一定初步的了解,也大致了解了應該如何選擇是使用JPA還是MyBatis選型。

後續幾篇系列文章中,將會一步步的介紹下Spring Data JPA的核心內容與具體項目實現,一步步的揭開JPA的廬山真面目。

如果通過本文介紹,你對JPA也有進一步了解的興趣,歡迎關注我的後續系列文檔。
如果對本文有自己的見解,或者有任何的疑問或建議,都可以留言,我們一起探討、共同進步。


我是悟道君,聊技術、又不僅僅聊技術~
期待與你一起探討,一起成長為更好的自己。