01 | Spring Data JPA 初识

news2024/11/25 12:34:39

Spring Boot 和 Spring Data JPA 的 Demo演示

我们利用 JPA + Spring Boot 简单做一个 RESTful API 接口,方便你来了解 Spring Data JPA 是干什么用的,具体步骤如下。

第一步:利用 IDEA 和 SpringBoot 2.3.3 快速创建一个案例项目。

点击“菜单” | New Project 命令,选择 Spring Initializr 选项,如下图所示。

Drawing 0.png

这里我们利用 Spring 官方的 Start 来创建一个项目,接下来选择 Spring Boot 的依赖:

  • Lombok:帮我们创建一个简单的 Entity 的 POJO,主要用来省去创建 GET 和 SET 方法;
  • Spring Web:MVC 必备组件;
  • Spring Data JPA:重头戏,这是本课时的重点内容;
  • H2 Database:内存数据库;
  • Spring Boot Actuator:监控我们项目状态使用。

然后通过下图操作界面选择上面提到的这些依赖,如下图所示:

Drawing 1.png

第二步:通过 IDEA 的图形化界面,一路单击 Next 按钮,然后单击 Finsh 按钮,得到一个工程,完成后结构如下图所示:

Drawing 2.png

现在我们已经可以创建一个 Spring Boot + JPA 的项目了,那么接下来我们看看怎么对 User 表进行增删改查操作。

第三步:新增 3 个类来完成对 User 的 CURD。

第一个类:新增 User.java,它是一个实体类,用来做 User 表的映射的,如下所示:

复制代码

package com.example.jpa.example1;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Data
public class User {
   @Id
   @GeneratedValue(strategy= GenerationType.AUTO)
   private Long id;
   private String name;
   private String email;
}

第二个类:新增 UserRepository,它是我们的 DAO 层,用来操作实体 User 进行增删改成操作,如下所示:

复制代码

package com.example.jpa.example1;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User,Long> {
}

第三个类:新增 UserController,它是 Controller,用来创建 Rest 的 API 的接口的,如下所示:

复制代码

package com.example.jpa.example1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(path = "/api/v1")
public class UserController {
   @Autowired
   private UserRepository userRepository;
   /**
    * 保存用户
    * @param user
    * @return
    */
   @PostMapping(path = "user",consumes = {MediaType.APPLICATION_JSON_VALUE})
   public User addNewUser(@RequestBody User user) {
      return userRepository.save(user);
   }
   /**
    * 根据分页信息查询用户
    * @param request
    * @return
    */
   @GetMapping(path = "users")
   @ResponseBody
   public Page<User> getAllUsers(Pageable request) {
      return userRepository.findAll(request);
   }
}

最终,我们的项目结构变成如下图所示的模样:

Drawing 3.png

上图中,appliaction.properties 里面的内容是空的,到现在三步搞定,其他什么都不需要配置,直接点击 JpaApplication 这个类,就可启动我们的项目了。

第四步:调用项目里面的 User 相关的 API 接口测试一下。

我们再新增一个 JpaApplication.http 文件,内容如下:

复制代码

POST /api/v1/user HTTP/1.1
Host: 127.0.0.1:8080
Content-Type: application/json
Cache-Control: no-cache
{"name":"jack","email":"123@126.com"}
#######
GET http://127.0.0.1:8080/api/v1/users?size=3&page=0
###

点击“运行”按钮,效果如下图所示:

Drawing 4.png

运行结果如下:

复制代码

POST http://127.0.0.1:8080/api/v1/user
HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 22 Aug 2020 02:48:43 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
  "id": 4,
  "name": "jack",
  "email": "123@126.com"
}
Response code: 200; Time: 30ms; Content length: 44 bytes
GET http://127.0.0.1:8080/api/v1/users?size=3&page=0
HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 22 Aug 2020 02:50:20 GMT
Keep-Alive: timeout=60
Connection: keep-alive
{
  "content": [
    {
      "id": 1,
      "name": "jack",
      "email": "123@126.com"
    },
    {
      "id": 2,
      "name": "jack",
      "email": "123@126.com"
    },
    {
      "id": 3,
      "name": "jack",
      "email": "123@126.com"
    }
  ],
  "pageable": {
    "sort": {
      "sorted": false,
      "unsorted": true,
      "empty": true
    },
    "offset": 0,
    "pageNumber": 0,
    "pageSize": 3,
    "unpaged": false,
    "paged": true
  },
  "totalPages": 2,
  "last": false,
  "totalElements": 4,
  "size": 3,
  "number": 0,
  "numberOfElements": 3,
  "sort": {
    "sorted": false,
    "unsorted": true,
    "empty": true
  },
  "first": true,
  "empty": false
}
Response code: 200; Time: 59ms; Content length: 449 bytes

关于 IDEA 运行 Gradle 项目的小技巧: 在实际工作中,我们启动运行或者是跑测试用例的时候,经常以 Gradle 的方式运行,或者用 Application 的方式运行,两种方式进行随意切换,需要设置的地方如下图所示:

Drawing 5.png

通过以上案例,我们知道了 Spring Data JPA 可以帮我们做数据的 CRUD 操作,掌握到了JPA + Spring Boot 如何启动和集成 JPA,以及对如何创建一个数据库操作也有了一定的了解。那么接下来,我们看下是如何切换默认数据源的,如切换成 MySQL。

JPA 如何整合 MySQL 数据库?

关于 JPA 与 MySQL 的集成我们分为两部分来展开:如何切换 MySQL 数据源、如何写测试用例进行测试。

1. 切换 MySQL 数据源

上面的例子,我们采用的是默认 H2 数据源的方式,这个时候你肯定会问:“H2 重启,数据丢失了怎么办?”那么我们调整一下上面的代码,以 MySQL 作为数据源,看看需要改动哪些。

第一处改动,application.properties 内容如下:

复制代码

spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.generate-ddl=true

第二处改动,删除 H2 数据源,新增 MySQL 数据库驱动:

Drawing 6.png

调整完毕之后,我们重启这个项目,以同样的方式测试上面的两个接口依然 OK。

Drawing 7.png

其实这个时候可以发现一件事情,那就是我没有手动去创建任何表,而 JPA 自动帮我创建了数据库的 DDL,并新增了 User 表,所以当我们用 JPA 之后创建表的工作就不会那么复杂了,我们只需要把实体写好就可以了。

以上是切换 MySQL 数据源需要进行的操作,接下来看看测试用例怎么写,在修改代码的时候我们就不需要频繁重启项目了,当你掌握 JUnit 之后,可以提升开发效率。

2. Spring Data JPA 测试用例的写法

我们这里只关注 Repository 的测试用例的写法,Controller 和 Service 等更复杂的测试我们在测试课时再详细介绍,这里我们先快速体验一下。

第一步,在 Test 目录里增加 UserRepositoryTest 类:

复制代码

package com.example.jpa.example1;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import java.util.List;
@DataJpaTest
public class UserRepositoryTest {
    @Autowired
    private UserRepository userRepository;
    @Test
    public void testSaveUser() {
        User user = userRepository.save(User.builder().name("jackxx").email("123456@126.com").build());
        Assert.assertNotNull(user);
        List<User> users= userRepository.findAll();
        System.out.println(users);
        Assert.assertNotNull(users);
    }
}

第二步,我们可直接运行测试用例,进行真实的 DB 操作,通过控制台来看下我们的测试用例是否能够跑通,如下图所示:

Drawing 8.png

通过上图可以看到,测试的时候执行的 SQL 有哪些,那么我们到底是连接的 MySQL 做的测试用例,还是连接的 H2 做的测试呢?在后面的第 30 课时(单元测试和集成测试)的时候我会为你详细揭晓,到时你会发现测试用例写起来也是如此简单。

整体认识 JPA

通过上面的两个例子我们已经快速入门了,知道了 Spring Boot 结合 Spring Data JPA 怎么配置和启动一个项目 ,之后当你熟悉了 JPA 之后,你还会发现 Spring Boot JPA 要比我们配置 MyBatis 简单很多。下面我们来整体认识一下 Java Persistence API 究竟是什么。

介绍 JPA 协议之前,我们先来对比了解下市面上的 ORM 框架有哪些,分别有哪些优缺点,做到心里有数。

1. 市场上 ORM 框架比对

下表是市场上比较流行的 ORM 框架,这里我罗列了 MyBatis、Hibernate、Spring Data JPA 等,并对比了下它们的优缺点。

2.png

经过对比,你可以看到我们正在学习的 Spring Data JPA 还是比较前卫的,很受欢迎,继承了 Hibernate 的很多优点,上手又比较简单。所以,我非常建议你好好学习一下。

2. Java Persistence API 介绍和开源实现

JPA 是 JDK 5.0 新增的协议,通过相关持久层注解(@Entity 里面的各种注解)来描述对象和关系型数据里面的表映射关系,并将 Java 项目运行期的实体对象,通过一种Session持久化到数据库中。

想象一下,一旦协议有了,大家都遵守了此种协议进行开发,那么周边开源产品就会大量出现,比如我们在后面要介绍的第 29 课时(Spring Data Rest 是什么?和 JPA 是什么关系?)就可以基于这套标准,进而对 Entity 的操作再进行封装,从而可以得到更加全面的 Rest 协议的 API接口。

再比如 JSON API(https://jsonapi.org/)协议,就是雅虎的大牛基于 JPA 的协议的基础,封装制定的一套 RESTful 风格、JSON 格式的 API 协议,那么一旦 JSON API 协议成了标准,就会有很多周边开源产品出现。比如很多 JSON API 的客户端、现在比较流行的 Ember 前端框架,就是基于 Entity 这套 JPA 服务端的协议,在前端解析 API 协议,从而可以对普通 JSON 和 JSON API 的操作进行再封装。

所以规范是一件很有意思的事情,突然之间世界大变样,很多东西都一样了,我们的思路就需要转换了。

JPA 的内容分类

  • 一套 API 标准定义了一套接口,在 javax.persistence 的包下面,用来操作实体对象,执行 CRUD 操作,而实现的框架(Hibernate)替代我们完成所有的事情,让开发者从烦琐的 JDBC 和 SQL 代码中解脱出来,更加聚焦自己的业务代码,并且使架构师架构出来的代码更加可控。
  • 定义了一套基于对象的 SQL:Java Persistence Query Language(JPQL),像 Hibernate 一样,我们通过写面向对象(JPQL)而非面向数据库的查询语言(SQL)查询数据,避免了程序与数据库 SQL 语句耦合严重,比较适合跨数据源的场景(一会儿 MySQL,一会儿 Oracle 等)。
  • ORM(Object/Relational Metadata)对象注解映射关系,JPA 直接通过注解的方式来表示 Java 的实体对象及元数据对象和数据表之间的映射关系,框架将实体对象与 Session 进行关联,通过操作 Session 中不通实体的状态,从而实现数据库的操作,并实现持久化到数据库表中的操作,与 DB 实现同步。

详细的协议内容你感兴趣的话也可以看一下官方的文档。

JPA 的开源实现

JPA 的宗旨是为 POJO 提供持久化标准规范,可以集成在 Spring 的全家桶使用,也可以直接写独立 application 使用,任何用到 DB 操作的场景,都可以使用,极大地方便开发和测试,所以 JPA 的理念已经深入人心了。Spring Data JPA、Hibernate 3.2+、TopLink 10.1.3 以及 OpenJPA、QueryDSL 都是实现 JPA 协议的框架,他们之间的关系结构如下图所示:

Drawing 9.png

俗话说得好:“未来已经来临,只是尚未流行”,大神资深开发用 Spring Data JPA,编程极客者用 JPA;而普通 Java 开发者,不想去挑战的 Java“搬砖者”用 Mybatis。

到这里,相信你已经对 JPA 有了一定的认识,接下来我们了解一下 Spring Data,看看它都有哪些子项目。

Spring Data 认识

1. Spring Data 介绍

Spring Data 项目是从 2010 年开发发展起来的,Spring Data 利用一个大家熟悉的、一致的、基于“注解”的数据访问编程模型,做一些公共操作的封装,它可以轻松地让开发者使用数据库访问技术,包括关系数据库、非关系数据库(NoSQL)。同时又有不同的数据框架的实现,保留了每个底层数据存储结构的特殊特性。

Spring Data Common 是 Spring Data 所有模块的公共部分,该项目提供了基于 Spring 的共享基础设施,它提供了基于 repository 接口以 DB 操作的一些封装,以及一个坚持在 Java 实体类上标注元数据的模型。

Spring Data 不仅对传统的数据库访问技术如 JDBC、Hibernate、JDO、TopLick、JPA、MyBatis 做了很好的支持和扩展、抽象、提供方便的操作方法,还对 MongoDb、KeyValue、Redis、LDAP、Cassandra 等非关系数据的 NoSQL 做了不同的实现版本,方便我们开发者触类旁通。

其实这种接口型的编程模式可以让我们很好地学习 Java 的封装思想,实现对操作的进一步抽象,我们也可以把这种思想运用在自己公司写的 Framework 上面。

下面来看一下 Spring Data 的子项目都有哪些。

2. Spring Data 的子项目有哪些

下图为目前 Spring Data 的框架分类结构图,里面都有哪些模块可以一目了然,也可以知道哪些是我们需要关心的项目。

Drawing 11.png

主要项目(Main Modules):

  • Spring Data Commons,相当于定义了一套抽象的接口,下一课时我们会具体介绍
  • Spring Data Gemfire
  • Spring Data JPA,我们关注的重点,对 Spring Data Common 的接口的 JPA 协议的实现
  • Spring Data KeyValue
  • Spring Data LDAP
  • Spring Data MongoDB
  • Spring Data REST
  • Spring Data Redis
  • Spring Data for Apache Cassandra
  • Spring Data for Apache Solr

社区支持的项目(Community Modules):

  • Spring Data Aerospike
  • Spring Data Couchbase
  • Spring Data DynamoDB
  • Spring Data Elasticsearch
  • Spring Data Hazelcast
  • Spring Data Jest
  • Spring Data Neo4j
  • Spring Data Vault

其他(Related Modules):

  • Spring Data JDBC Extensions
  • Spring for Apache Hadoop
  • Spring Content

关于 Spring Data 的子项目,除了上面这些,还有很多开源社区版本,比如 Spring Data、MyBatis 等,这里就不一一介绍了,感兴趣的同学可以到 Spring 社区,或者 GitHub 上进行查阅。

总结

本课时的主要目的是带领你快速入门,从 H2 数据源和 Mysql 数据源两个方面为你介绍了 Spring Data JPA 数据操作的概念,了解了 Repository 的写法,快速体验一把 Spring Data JPA 的便捷之处。

希望你通过本节课的学习可以对 Spring Data JPA + Spring Boot 有一个整体的认识,为以后的技术进阶打下良好的基础。在掌握了基本知识以后,你会发现 Spring Data JPA 是 ORM 的效率利器,后面课程我会一一揭开 Spring Data JPA 的神秘面纱,带你掌握其实现原理和实战经验,让你在实际开发中游刃有余。

对于本课时所讲的知识点,欢迎你在下方留言区表达自己的学习感悟,大家一起讨论,共同进步。

补充一个TIPS:课程中的案例是依赖 lombok 插件的,如下图所示:

image (3).png

并开启 annotation processing。

image (4).png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1091558.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2.MySQL表的操作

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 表的操作 (1)表的创建 CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎; 存储引擎的不同会导致创建表的文件不同。 换个引擎。 t…

【C语言】结构体、位段、枚举、联合(共用体)

结构体 结构&#xff1a;一些值的集合&#xff0c;这些值称为成员变量。结构体的每个成员可以是不同类型的变量&#xff1b; 结构体声明&#xff1a;struct是结构体关键字&#xff0c;结构体声明不能省略struct&#xff1b; 匿名结构体&#xff1a;只能在声明结构体的时候声…

伦敦银单位转换很简单

伦敦银源自于英国伦敦的电子化的白银投资方式&#xff0c;高杠杆和高收益的它的基本属性&#xff0c;但有别于国内大家所熟悉的投资品种&#xff0c;伦敦银在交易过程中有很多不一样的地方&#xff0c;需要大家地去留意。 比如伦敦银的计价单位是盎司&#xff0c;而且具体来说…

【Qt上位机】打开本地表格文件并获取其中全部数据

前言 其实本文所实现的功能并非博主要实现的全部功能&#xff0c;只是全部功能中的一小部分&#xff0c;这里只是为了记录一下实现方法&#xff0c;防止后续忘记&#xff0c;仅供参考。 文章目录 一、实现效果二、UI设计三、程序设计3.1 选择本地表格文件3.2 获取表格总行列数3…

百度Echarts实现饼图,较官网示例更多项显示

本来是想直接使用官网示例修改几个地方就用起来&#xff0c;但是用户希望一眼就看到百分占比&#xff0c;但是官网示例没有使用lable的&#xff0c;找了半天都没找到&#xff0c;后来通过对比其他饼图发现lable这个项&#xff0c;再次记录一下 首先看效果图&#xff1a; 2. 代码…

国海证券:36氪(KRKR):新经济内容平台龙头,多元变现可期

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 猛兽财经获悉&#xff0c;国海证券今日发布了关于36氪的新经济内容平台龙头&#xff0c;多元变现可期研报。国海证券主要内容如下&#xff1a;1、新经济产业发展迅猛&#xff0c;36氪定位为以媒体为旗舰的新经济服务集团&a…

下载安装Ipa Guard

下载安装Ipa Guard 可以前往ipaguard工具官网下载&#xff0c;工具是免费下载&#xff0c;免费体验使用的。下载地址是https://www.ipaguard.com。 下载后解压工具便ok了&#xff0c;工具是绿色软件&#xff0c;无需其他安装流程。双击Ipa Guard.exe 启动ipaguard。 ipaguard…

【问题思考】如何通过参数式求出方向向量?(待深入本质)

问题 今天在做23李六第二套的时候看到了一道题&#xff1a; 答案里面说的直接再加一个yy和上面的两个方程就凑成了三个方程&#xff08;x关于y的&#xff0c;y关于y的&#xff0c;z关于y的&#xff0c;最后每个方程都对y求导&#xff0c;再代入y1&#xff0c;就有了方向向量&…

Netapp数据恢复—Netapp存储误删除lun的数据恢复过程

Netapp存储数据恢复环境&#xff1a; 北京某公司一台netAPP存储&#xff0c;72块SAS硬盘划分了若干个lun。 Netapp存储故障&#xff1a; 工作人员误操作删除了12个lun。 Netapp存储数据恢复过程&#xff1a; 1、将故障存储中所有磁盘编号后取出&#xff0c;以只读方式做全盘镜…

C++入门指南:类和对象总结笔记(下)

C入门指南:类和对象总结笔记&#xff08;下&#xff09; 一、深度剖析构造函数1.1 构造函数体赋值1.2 初始化列表1.3 explicit关键字 二、static成员2.1 概念2.2 特性 三、友元3.1 友元函数3.2 友元类 四、 内部类4.1 概念4.2 特征 五、拷贝对象时的一些编译器优化六、深度剖析…

论文浅尝 | 深度神经网络的模型压缩

笔记整理&#xff1a;闵德海&#xff0c;东南大学硕士&#xff0c;研究方向为知识图谱 链接&#xff1a;https://arxiv.org/abs/1412.6550 动机 提高神经网络的深度通常可以提高网络性能&#xff0c;但它也使基于梯度的训练更加困难&#xff0c;因为更深的网络往往更加强的非线…

​人机交互中的反馈与前馈

人机交互中的反馈和前馈&#xff0c;是指在用户与机器进行交互的过程中&#xff0c;人机二者对输入的信息做出回应的方式。 反馈&#xff1a;反馈是从机器到人的信息传递过程&#xff0c;主要用于告知用户他们的操作或请求的结果。当用户执行某个操作时&#xff0c;机器通过适当…

nginx生成https 证书-基于docker-compose

申请的证书存放nginx的docker-compose.yml同一目录 [rootk8s-node1 nginx]# cat docker-compose.yml version: 2 services:nginx:container_name: nginximage: nginxrestart: alwaysvolumes:- "./default.conf:/etc/nginx/conf.d/default.conf"- "./nginx.conf…

初级问题 程序中的变量是指什么?中级问题 把若干个数据沿直线排列起来的数据结构叫作什么?高级问题 栈和队列的区别是什么?

目录 1.深刻主题 2.描写复杂人物 初级问题 程序中的变量是指什么&#xff1f; 中级问题 把若干个数据沿直线排列起来的数据结构叫作什么&#xff1f; 高级问题 栈和队列的区别是什么&#xff1f; 计算机图形学&#xff08;有效边表算法&#xff09; 介绍一下计算机图形学…

LoRa技术在实际应用中可能遇到的问题和挑战,以及解决方案

LoRa技术在物联网和其他应用领域中取得了显著的成功&#xff0c;但在实际应用中仍然面临一些问题和挑战。以下是一些可能的问题和挑战&#xff0c;以及针对这些挑战的一些建议解决方案。 1. 频谱管理问题 问题&#xff1a; 由于LoRa使用公共频谱&#xff0c;频道拥塞和干扰可…

java中转义字符的源码数据格式,内存存储数据格式和转换json后的数据格式

转义字符在内存存储格式 于 转换json后发送的数据格式是不一样的。因为json对于java来说可以看成一种源码&#xff0c;那就需要以源码的表示格式输出。 要注意转义字符在每种语言的源码的数据格式 和 内存存储的数据格式。 例&#xff1a;\n 换行转义字符 1.在java源码中为\…

一些基本的 AFL++ 插桩模式操控方式 (还有 DEBUG 方式)

在 afl-cc.c 1807 行&#xff0c;可以看到如下代码 " You can also use the old environment variables instead:\n" " AFL_LLVM_USE_TRACE_PC: use LLVM trace-pc-guard instrumentation\n" " AFL_LLVM_CALLER: use single context sensitive covera…

基于文心一言打造AI应用,律品汇助推公共法律服务惠及中国乡村

“宅基地可以买卖吗&#xff1f;” “邻居家建房子占了我的地&#xff0c;我该怎么办&#xff1f; “我给房东签了定金&#xff0c;现在我不打算租这个房子了&#xff0c;对方要不要退我定金啊&#xff1f;” 这些问题&#xff0c;仅仅是云南某村居民诸多法律咨询内容的一角&am…

SpringBoot 过滤器filter当中的自定义异常捕获问题

需求描述&#xff1a;需要根据用户的请求路径拦截做权限控制&#xff1a; 但是这样做全局异常无法捕获 解决方案&#xff1a; 在filter当中引入HandlerExceptionResolver类&#xff0c;通过该类的resolveException方法抛出自定义异常&#xff1a; public class OpenInvokeFil…

游戏中的随机——“动态平衡概率”算法

前言 众所周知计算机模拟的随机是伪随机&#xff0c;但在结果看来依然和现实中的随机差别不大。 例如掷硬币&#xff0c;连续掷很多很多次之后&#xff0c;总有连续七八十来次同一个面朝上的情况出现&#xff0c;计算机中一般的随机函数也能很好模拟这一点。 但在游戏中&…