选Spring Data JPA,还是MyBatis?

‍‍‍‍‍‍‍‍‍‍‍‍


文章来源:【公众号:架构悟道】

目录

  • 前言

  • 需要厘清的若干概念

  • 选择 Spring Data JPA 的理由

  • 小结

前言

Spring Data JPA 作为 Spring Data 中对于关系型数据库支持的一种框架技术,属于 ORM 的一种,通过得当的使用,可以大大简化开发过程中对于数据操作的复杂度。

本文要对 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 的正确印象。

需要厘清的若干概念

| JDBC

谈到 Java 操作数据库相关的概念,JDBC 是绕不过去的一个概念。先来介绍下 JDBC 究竟是个什么概念。

JDBC(Java DataBase Connectivity),是 Java 连接数据库操作的原生接口。

JDBC 对 Java 程序员而言是 API,为数据库访问提供标准的接口。由各个数据库厂商及第三方中间件厂商依照 JDBC 规范为数据库的连接提供的标准方法。

e4ab8ceccab9adc3a5deba0417370c9e.png

概念阐述的可能稍微有点抽象,说的直白点可以这么理解:各个产商的 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 进行编码开发的,而是借助一些封装框架来实现。

| ORM 框架

对象-关系映射(Object-Relational Mapping,简称 ORM)。ORM 框架中贯穿着 Java 面向对象编程的思想,是面向对象编程的优秀代言人。

直白点说,ORM 就是将代码里面的 Java 类与 DB 中的 table 表进行映射,代码中对相关 Java 类的操作,即体现为 DB 中对相关 Table 的操作。

ORM 框架很好解决了 JDBC 存在的一系列问题,简化了 Java 开发人员的编码复杂度。

| 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 程序对数据库数据的操作。

3a8fd625a21eccd0f8fea987b9100952.png


| Spring Data JPA

基于前面介绍,我们了解到 JPA 的基本概念,知晓 JPA 其实是一个基于 ORM 的 Java API 规范定义,那么这里提及的 Spring Data JPA 又是什么呢?其与 JPA 之间的关系又是如何呢?

Spirng Data JPA 是 Spring 提供的一套简化 JPA 开发的框架,按照约定好的【方法命名规则】写 DAO 层接口,就可以在不写接口实现的情况下,实现对数据库的访问和操作,同时提供了很多除了 CRUD 之外的功能,如分页、排序、复杂查询等等。

3f430dbd43204f65ea30e40211f71d65.png

注意:Spring Data JPA 不是一个完整 JPA 规范的实现,它只是一个代码抽象层,主要用于减少为各种持久层存储实现数据访问层所需的代码量。其底层依旧是 Hibernate。

可以把 Spring Data JPA 理解为 JPA 规范的再次封装抽象。

‍‍‍‍‍‍‍‍‍‍‍| Hibernate

Hibernate 是一个标准的 ORM 框架,实现 JPA 接口。

| 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)。

相互之间的关系详解,见下图示意:

82da5efdb89c08f4c030d9b8457363ba.png

‍‍‍‍‍‍‍‍‍‍

选择 Spring Data JPA 的理由


| Spring Data JPA 的优势

在介绍 Spring Data JPA 的优势前,先看个代码例子。

场景:一张用户表(UserEntity),信息如下:

53cd9ceb834dd7fd6cc610e408be9075.png

代码中实现如下诉求:

获取所有研发部门的人员:

List<UserEntity> users = userReposity.findAllByDepartment("DevDept");

获取研发部门的管理员:

List<UserEntity> users = userReposity.findAllByDepartmentAndRole("DevDept", "Admin");

看完上面的例子,一个最直观的感受是什么?

简单!没错,“简单”就是 Spring Data JPA 最大的优势!

对于大部分的常规操作,基于 Spring Data JPA,开发人员可以更加专注于业务逻辑的开发,而不用花费太多的精力去关注 DB 层面的封装处理以及 SQL 的编写维护,甚至在 DAO 层都不需要去定义接口。

除了简化开发,JPA 还有的另一个比较大的优势,就是其可移植性比较好,因为其通过 JPQL 的方式进行操作,与原生 SQL 之间几乎没有耦合,所以可以方便的将底层 DB 切换到别的类型。

| Spring Data JPA 整体实现逻辑

基于前面的介绍,我们可以这样理解,Java 业务层调用 SpringData JPA 二次封装提供的 Repository 层接口,进而基于 JPA 标准 API 进行处理,基于 Hibernate 提供的 JPA 具体实现,接着基于 JDBC 标准 API 接口,完成与实际 DB 之间的请求交互。

整体的处理逻辑全貌图如下:

703270c4358bd21d7e6f64eb27b29eb9.png

这里可以看出,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。‍‍‍‍‍‍‍‍‍‍‍‍


| 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 关键字的搜索热度与区域的数据,如下所示:

c4a403d18d8178e80de641783fd24813.png

从图中可以看出,MyBatis 在中国地区相对更受欢迎一些,但是在日本 JPA 的受欢迎度要更高一些。

小结

好啦,本篇内容就介绍到这里。通过本篇内容,对 Java 体系中 DB 操作相关的组件、规范等有了一定初步的了解,也大致了解了应该如何选择是使用 JPA 还是 MyBatis 选型。

‍‍‍‍‍‍‍‍‍‍‍‍后续将会介绍 Spring Data JPA 的核心内容与具体项目实现,一步步的揭开 JPA 的庐山真面目。‍‍‍‍‍‍‍‍‍‍‍‍

-------------  END  -------------
扫码免费获取600+页石杉老师原创精品文章汇总PDF



原创技术文章汇总


点个在看你最好看
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值