第9章 Spring Boot整合JPA 与 JpaRepository 基础方法介绍

2023-05-16

参考文章:

第1章 Spring Boot到底是什么?_陈小房的博客-CSDN博客

第2章 第一个Spring Boot项目_陈小房的博客-CSDN博客

第3章 Spring Boot项目配置详解_陈小房的博客-CSDN博客

第4章 Spring Boot的Web应用开发入门_陈小房的博客-CSDN博客

第5章 Spring Boot模板Thymeleaf入门详解_陈小房的博客-CSDN博客

第6章 MyBatis框架入门详解(1)_陈小房的博客-CSDN博客

第7章 MyBatis框架入门详解(2)_陈小房的博客-CSDN博客

第8章 使用注解的方式整合MyBatis 入门详解_陈小房的博客-CSDN博客

 

目录 

1. 什么是JPA

1.1 JPA和MyBatis的关系

2. Spring Data JPA

2.1 配置SpringData JPA

3. 验证Spring Data JPA

 4. JpaRepository类定义

5. JpaRepository基础方法

5.1 新增数据

save

saveAll

5. 2 更新数据库方法

5.3 查找数据

findById

findAll

findAllById

existsById

 findAll(Sort sort)

findAll(Pageable pageable)

count

5.4 数据删除

deleteById

deleteAll()


1. 什么是JPA

   JPA(Java Persistence API, Java 持久化API)是SUN公司提出的Java持久化规范,它提供了一种对象/关系映射的管理工具来管理Java中的关系型数据库。JPA的主要目的是简化现有的持久化开发工作并且整合ORM框架,JPA本身并不是ORM框架,它是一种规范,这种规范可以私下通过注解或者XML描述“对象-关系表”之间的映射关系,并将实体对象持久化到数据库中,从而极大地简化现有的持久化开发工作。

1.1 JPA和MyBatis的关系

    实现JPA的框架有Hibernate, TopLink, 而我们前面介绍的MyBatis不属于实现JPA的框架,主要区别有:

  1. Mybatis是对象和结果集的映射,而JPA规范强调的是对象和关系表之间的映射。
  2. 遵守JPA规范的框架具有良好的移植性,不用关心用什么数据库,而Mybatis框架在更改数据库时需要修改底层SQL。

2. Spring Data JPA

2.1 配置SpringData JPA

    Spring Data 是Spring 的一个子项目, 旨在统一和简化对各类型持久化存储, 而不拘泥于是关系型数据库还是NoSQL 数据存储。

   Spring Data JPA是Spring Data项目的一部分,它是在ORM框架思想、JPA规范的基础上封装的一套JPA应用框架。使用Spring Data JPA只需要继承和扩展Spring Data 中统一的数据访问接口Repository接口无需编写SQL实现数据库访问。

在pom.xml文件中添加spring-boot-starter-data-jpa依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

在数据库中新建一个schema用于JPA测试

 然后在application.properties文件中进行相关配置

spring.datasource.url=jdbc:mysql://localhost:3306/jpa_demo?useSSL=true&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=itJMF-4RObQ2
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

#JPA 配置
spring.jpa.hibernate.ddl-auto=update
#spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

 这里对JPA配置进行简单说明

 spring.jpa.hibernate.ddl-auto

该配置比较常用,配置实体类维护数据库表结构的具体行为。它主要有4个选项

  1. create: 启动时删数据库中的表,然后创建新表,退出时不删除数据表
  2. create-drop: 启动时删数据库中的表,然后创建,退出时删除数据表 如果表不存在则报错
  3. update: 如果启动时表格式不一致则更新表,原有数据保留
  4. validate: 项目启动表结构进行校验 如果不一致则报错”

这里我们选择了update

spring.jpa.show-sql=true 操作时在控制台打印真实的SQL语句,便于调试

spring.jpa.properties.hibernate.format_sql=true 以JSON格式打印输出SQL语句方便查看

3. 验证Spring Data JPA

首先,创建Scenic实体类,它是一个实体类,按照JPA的设计思想,这个实体类也是定义数据库中的表结构的类,示例代码如下

@Entity
@Table(name = "scenics")
public class Scenic {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    private int scenicId;

    private int cityId;

    //@Column(name = "scenicName")
    @Column(length = 64)

    private String scenicName;

    private int price;


    public Scenic() {

    }

    public Scenic(Integer cityId, String scenicName, int price ){
        this.cityId = cityId;
        this.scenicName = scenicName;
        this.price = price;
    }

    public int getScenicId() {
        return scenicId;
    }

    public void setScenicId(int scenicId) {
        this.scenicId = scenicId;
    }

    public int getCityId() {
        return cityId;
    }

    public void setCityId(int cityId) {
        this.cityId = cityId;
    }

    public String getScenicName() {
        return scenicName;
    }

    public void setScenicName(String scenicName) {
        this.scenicName = scenicName;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }
}

 注意这个实体类中使用了JPA相关的注解

@Entity 这个注解是使用JPA时必须的注解,代表这个类对应了一个数据库表

@Table 这是一个可选的注解,用于说明数据库实体对应的表信息,包括表的名称、索引信息等,如果没有则表名和实体类的名称一致,一般情况下我们不使用该注解,这里为了演示,我们使用该注解将表名申明为Scenics

@Id 代表对应的主键

@GeneratedValue 设置数据库主键自动生成规则。strategy属性提供4种选项

AUTO:主键由程序控制,是默认选项。

IDENTITY:主键由数据库自动生成,即采用数据库ID自增长的方式,注意Oracle不支持这种方式。

SEQUENCE:通过数据库的序列产生主键,通过@SequenceGenerator注解指定序列名,注意MySQL不支持这种方式。

TABLE:通过特定的数据库表产生主键,使用该策略可以使应用更易于数据库移植。

@Column注解:声明实体属性的表字段的定义。默认的实体每个属性都对应表的一个字段,字段名默认与属性名保持一致。字段的类型根据实体属性类型自动对应。这里主要声明了字符字段的长度length,如果不声明,则系统会采用255作为该字段的长度。

这里需要注意JPA自动建表的字段命名规则采用的是下划线,如属性scenicName会将生成数据库字段scenic_name,如果需要生成非下划线字段,可以采用@Column(name = "ScenicName")

运行测试

运行Spring boot应用,控制台输出

  查看数据库,可以看到已经自动创建了scenics数据库表

   

 4. JpaRepository类定义

  接下来学习如何通过类来操作数据库,在Spring Data JPA中使用JpaRepository接口类完成对数据库的操作。JpaRepository是Spring Data JPA中最重要的类之一。

 这是JpaRepository接口的定义

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>

 可以看出JpaRepository继承了接口PagingAndSortingRepository和QueryByExampleExecutor。而PagingAndSortingRepository又继承CrudRepository。

@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {

 所以JpaRepository接口同时拥有了基本CRUD功能以及分页功能。

 JpaRepository提供了30多个默认方法,基本能满足项目中的数据库操作功能。当我们需要定义自己的Repository接口的时候,我们可以直接继承JpaRepository,从而获得SpringBoot Data JPA为我们内置的多种基本数据操作方法。

5. JpaRepository基础方法

下面对主要的方法进行测试

在项目目录下新建repository包,添加接口文件ScenicRepository

 代码如下 

@Repository
public interface ScenicRepository extends JpaRepository<Scenic, Integer> {
}

 在测试用例类Chapter9ApplicationTests中添加测试方法进行测试

5.1 新增数据

save

JPARepository接口提供save方法用于新增数据,它的使用很简单,只要传入需要新增的实体类即可

    @Resource
    private ScenicRepository scenicRepository;

    @Test
    public void testSave() {

        Scenic scenic = new Scenic(1,  "scenic1", 10);
        scenicRepository.save(scenic);
    }

 执行结果

 saveAll

如果需要批量新增则可以使用saveAll方法

    @Test
    public void testSaveAll() {
        List<Scenic> scenicList = new ArrayList<>();
        scenicList.add(new Scenic(11, "savaAll_11", 100));
        scenicList.add(new Scenic(12, "saveAll_12", 200));
        scenicList.add(new Scenic(13, "saveAll_13", 300));
        scenicRepository.saveAll(scenicList);
    }

 执行结果

 5. 2 更新数据库方法

 更新已有数据库的方法也是save  

    @Test
    public void testUpdate() {
        Scenic scenic = scenicRepository.findById(1).get();
        scenic.setScenicName("scenicUpdate");
        scenicRepository.save(scenic);
    }

  执行结果

  

5.3 查找数据

findById

可以根据id查询对应的实体,函数原型如下

    /**
	 * 根据id查询对应的实体。
	 */
	Optional<T> findById(ID id);

 测试代码

    @Test
    public void testFindById() {
        Scenic scenic = scenicRepository.findById(2).get();
        System.out.println(scenic.getScenicName() + ":" + scenic.getScenicId());
    }

 执行输出 

findAll

查询所有的实体。方法原型

Iterable<T> findAll();

测试代码

    @Test
    public void testFindAll() {
        List<Scenic> scenicList = scenicRepository.findAll();
        for(Scenic scenic: scenicList) {
            System.out.println( scenic.getScenicName()+ ":" + scenic.getScenicId() + ":" + scenic.getPrice());
        }
    }

 测试结果

findAllById

如果不想查询全部数据,但是需要根据给定的Id查询部分数据,可以使用findAllById

    @Test
    public void testFindAllById() {
        List<Integer> idList = new ArrayList<>();
        idList.add(2);
        idList.add(3);

        List<Scenic> scenicList = scenicRepository.findAllById(idList);
        for (Scenic scenic : scenicList) {
            System.out.println(scenic.getScenicName() + ":" + scenic.getScenicId() + ":" + scenic.getPrice());
        }
    }

 测试结果

existsById

有时候我们并不想查找数据,而是只想知道数据是否存在与数据库表中,这个时候可以用existsById

boolean existsById(ID id);

测试代码

    @Test
    public void testExistsById() {
        System.out.println(scenicRepository.existsById(1));
    }

 测试结果

 findAll(Sort sort)

有时候需要对查询到的数据进行排序,此时可以传递一个排序函数。例如我们对secenic查询结果按照price降序排列

    @Test
    public void testFindAllSort() {
        Sort sort = Sort.by(Sort.Direction.DESC, "price");
        List<Scenic> scenicList = scenicRepository.findAll(sort);

        for(Scenic scenic: scenicList) {
            System.out.println( scenic.getScenicName()+ ":" + scenic.getScenicId() + ":" + scenic.getPrice());
        }
    }

执行结果

findAll(Pageable pageable)

返回一页实体,根据Pageable参数提供的规则进行过滤

    @Test
    public void testFindAllPageable() {

        // 分页查询
        // PageRequest.of 的第一个参数表示第几页(注意:第一页从序号0开始),第二个参数表示每页的大小
        // PageRequest of(int page, int size)
        Pageable pageable = PageRequest.of(1, 2);

        Page<Scenic> page = scenicRepository.findAll(pageable);
        System.out.println("总页数:" + page.getTotalPages());
        System.out.println("总记录数:" + page.getTotalElements());
        System.out.println("当前第几页:" + (page.getNumber() + 1));
        System.out.println("当前页面的记录数:" + page.getNumberOfElements());

    }

 测试结果

  count

 和SQL命令一样,用于统计数据元素个数

编写测试代码 

    @Test
    public void  testCount() {
        Long cnt = scenicRepository.count();
        System.out.println("元素个数: "+cnt);
    }

 运行结果

 5.4 数据删除

deleteById

根据id删除对应的数据

    @Test
    public void testDeleteById() {
        System.out.println("*************************");
        testFindAll();
        scenicRepository.deleteById(1);
        System.out.println("*************************");
        testFindAll();
        System.out.println("*************************");
    }

 删除前

 删除后

deleteAll()

deleteAll可以删除对应数据库表中的所有数据

    @Test
    public void testDeleteAll() {
        scenicRepository.deleteAll();
    }

 测试结果

  此外JPARepository还提供了delete(T entity) deleteAll(Iterable<? extends T> entities)可以根据一个或者多个具体实体删除

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

第9章 Spring Boot整合JPA 与 JpaRepository 基础方法介绍 的相关文章

  • 【Linux信号量】

    Linux信号量 POSIX信号量信号量的原理信号量的概念信号量函数 二元信号量模拟实现互斥功能基于环形队列的生产消费模型空间资源和数据资源生产者和消费者申请和释放资源必须遵守的两个规则信号量保护环形队列的原理 POSIX信号量 信号量的原
  • win11系统任务栏居中以及透明美化

    win11系统任务栏居中以及透明美化 文章目录 win11系统任务栏居中以及透明美化前言一 win11系统任务栏居中二 使用步骤1 如何找的安装的startallback2 startallback的功能 总结 前言 拥有一个漂亮的桌面会使
  • 求conio头文件

    conio头文件哪里下载呀
  • C语言程序设计:删除字符串中的数字

    题目内容 xff1a 编程 xff1a 从键盘上输入一个含有数字的字符串 xff0c 然后在 原字符串 中删除其中的数字 如输入的字符串为 ab12cd345e xff0c 则处理后的字符串为 abcde 程序中只能定义一个数组 提示 xf
  • 在Windows Server 2016 中共享及权限的操作

    如图 技术部 张工 蔡工 研发部 黄工 xff08 头儿 xff09 软件部 李工 周工 首先 xff0c 创建组和用户 xff0c 在服务管理器 工具 计算机管理 用户和组
  • 基于ssm的个人健康信息管理系统

    结合当今大数据技术研究的潮流 综合ssm框架 jsp技术 MySQL数据库等关键技术 构建了一个基于ssm的个人健康信息管理系统 首先 本文对个人健康信息管理系统涉及到的理论与相关技术进行了全面的分析 随后 通过对个人健康信息定义的理解和对
  • linux创建sftp

    SFTP简介 百度百科 xff1a sftp是Secure File Transfer Protocol的缩写 xff0c 安全文件传送协议 可以为传输文件提供一种安全的网络的加密方法 SFTP 为 SSH的其中一部分 xff0c 是一种传
  • Altium Designer 16.1中绘制蛇形走线的方法

    这是在线已经连接好的情况下进行的蛇形走线 1 首先英文输入法的情况下 xff0c 按下快捷键T 43 R xff0c 鼠标变成十字形 xff0c 点击需要进行蛇形走线的线段 2 然后按下Tab键 xff0c 设置蛇形走线参数 3 我一般选择
  • 5 计算机组成原理第四章 指令系统

    文章目录 1 指令格式1 1 指令定义1 2 指令格式1 3 指令格式 地址码1 4 指令格式 操作码1 5 操作码分类1 6 操作类型 2 数据存放指令寻址2 1 数据存放方式2 2 指令寻址2 3 操作数类型2 4 数据寻址2 4 1立
  • html ----checkbox使用

    1 html checkbox使用 lt html gt lt head gt lt title gt 选择 lt title gt lt head gt lt body gt 请选择你喜欢的水果 xff1a lt br gt lt for
  • Qt:QJsonArray

    说明 QJsonArray中存储了一系列的QJsonValue 可以向其中插入 删除QJsonValue 一个QJsonArray可以与QVariantList互相转换 可以通过size 访问其中的元素数 xff0c insert remo
  • Qt——日志输出

    普通的打印输出 用 QtCreator 开发 Qt 程序时 xff0c 经常需要向控制台打印一些参数 有时候是查看对象的属性是否被正确设置 xff0c 有时候是查看程序是否执行了某一段代码 xff0c 或者执行了多少次这一段代码 尽管使用调
  • 消息队列的重要技术讲解

    一 什么是消息队列 xff1f 消息队列不知道大家看到这个词的时候 xff0c 会不会觉得它是一个比较高端的技术 xff0c 反正我是觉得它好像是挺牛逼的 消息队列 xff0c 一般我们会简称它为MQ Message Queue xff0c
  • [android nfc] onNewIntent 中 无法获取 tag, 或者 intent.extras 为空, 或者 intent.action 为空

    在做android nfc 场景的时候 大方向上有2种 foreground 调度系统enableReaderMode api foreground 调度系统 发现android12下无法获取tag信息 经过排查 原因如下 在 androi
  • linux系统常用命令列举

    Linux系统入门 Linux特点 开源多用户 xff1a 系统可以在保证各个用户之间的安全 xff0c 隐私多任务 xff1a 良好的界面 xff1a Linux同时支持两种环境 xff0c 字符界面 图形化界面支持多种平台 xff1a
  • linux 常用命令

    查看所有分区 du sh window 想查看进程的端口号有这样几个方法 1 使用netstat ano查看所有连接和监听端口 xff0c 以及每个连接相关的进程ID 2 使用进程管理器查看进程PID 默认情况下可能不显示PID xff0c
  • android 11 Setting panel的一次源码分析

    Android 11 Setting panel的一次源码分析 Android 11关于Wi Fi的开关等设置 xff0c 不允许用户直接调用 xff0c 需要从panel设置 启动代码如下 xff1a val panelIntent 61
  • nginx与ftp服务器出现403错误

    默认的yum安装 ftp的路径是在 etc vsftpd xff0c 这时候通过上面创建的 用户从 FTP登陆后 进入 home目录就可以查看到ftpuser文件夹 上图这里有个小细节就是在Linux中 xff0c 创建一个文件时 xff0
  • 高通Android平台硬件调试之Camera篇

    之前一段时间有幸在高通android平台上调试2款camera sensor xff0c 一款是OV的5M YUV sensor xff0c 支持jpeg out xff0c 同时也支持AF xff0c 调试比较比较简单 xff0c 因为别
  • 7 计算机组成原理第五章 中央处理器 数据通路

    文章目录 1 数据通路的功能和基本结构单总线1 1 数据通路的功能1 2 数据通路 基本结构单总线 2 数据通路 CPU内部单总线方式2 1 三种结构之间数据传送方式2 2 CPU内部单总线方式 例题 3 专用通路3 1 专用数据通路方式3

随机推荐

  • Python 记录日志简单好用,功能齐全(Loguru)

    Loguru 一个能彻底解放你的日志记录器 它即插即用 xff0c 具备多种方式滚动日志 自动压缩日志文件 定时删除等功能 除此之外 xff0c 多线程安全 高亮日志 日志告警等功能也不在话下 下面就给大家介绍一下这个强大工具的基本使用方法
  • linux设备驱动——andriod平台wlan驱动II——给军爷的答案

    转自 http wsqhs spaces live com c11 BlogPart BlogPart 61 blogview amp c 61 BlogPart amp partqs 61 amonth 3d4 26ayear 3d200
  • Linux 下 如何打 PATCH 及制作 DIFF

    Linux下patch的制作和应用 因为在u boot移植过程中 xff0c 有几处通用文件要修改 xff0c 如果每次都要手动修改就太麻烦了 制作补丁可以解决这个问题 学习资料的收集比较简单 xff0c 方法一类似于这种初级问题网上资料非
  • LINUX GIT 使用

    git show HEAD git show HEAD git show HEAD git show HEAD git diff 486ec madplay player c git diff 4863 856f git diff 4863
  • LINUX 输入子系统分析

    1 输入子系统架构Overview 输入子系统 xff08 Input Subsystem xff09 的架构如下图所示 输入子系统由 输入子系统核心层 xff08 Input Core xff09 xff0c 驱动层和事件处理层 xff0
  • Linux Kernel and Android 休眠与唤醒

    Table of Contents 简介 国际化 版本信息 对于休眠 suspend 的简单介绍 Linux Suspend 的流程 相关的文件 准备 冻结进程 让外设进入休眠 Resume Android 休眠 suspend 涉及到的文
  • 浅析linux下键盘设备工作和注册流程

    span style color 000000 a href http qgjie456 blog 163 com blog m 61 0 span style font size 6 http qgjie456 blog 163 com
  • linux内核信号处理

    信号是操作系统中一种很重要的通信方式 近几个版本中 信号处理这部份很少有大的变动 我们从用户空间的信号应用来分析Linux内核的信号实现方式 一 信号有关的数据结构 在task struct中有关的信号结构 struct task stru
  • win7和ubuntu双系统,直接进入windows启动项选择菜单,而不进入grub的解决方案。

    一 Ubuntu 采用 grub 引导 xff0c 首先要将 grub 引导去掉 xff0c 重建 windows mbr 引导 xff0c 下载 MbrFix exe 并将它放到 C 盘根目录 xff08 其他目录也可 xff09 xff
  • 带你搞明白Zookeeper选举机制

    没什么 xff0c 搞不明白别打我就行 xff0c 初学者如有问题请及时指正 xff01 在上一篇文章我们有介绍3种server角色 xff1a Leader Follower以及Observer xff08 不参加选举 xff09 xff
  • windows远程linux桌面

    TigerVNC是一个高性能 平台无关的虚拟网络计算 xff08 Virtual Network Computing xff0c VNC xff09 实现 xff0c 是一个客户端 服务器应用程序 xff0c 允许用户在远程机器上启动并与图
  • 循环队列的介绍与实现

    文章目录 1 循环队列定义2 循环队列基本操作3 循环队列代码实现4 补充 1 循环队列定义 循环队列 xff1a 即顺序存储的队列 xff0c 是为了避免 假溢出 而利用 运算符将队列首尾相接连成一个环状的队列 xff0c 称为循环队列
  • AndroidStudio4.1 升级Kotlin插件不生效问题

    背景 xff0c 在使用SAM转换写Livedata observe 的第二个参数时 xff0c 发现AS报红 xff0c 但编译不出错 xff0c 功能也能正常运行 然后就尝试升级Kotlin插件 AndroidStudio4 1 默认带
  • 一个中科大差生的8年程序员工作总结

    今年终于从大菊花厂离职了 xff0c 离职前收入大概60w不到吧 xff0c 在某乎属于比较差的 xff0c 今天终于有空写一下自己的职场故事 xff0c 也算是给自己近8年的程序员工作做个总结复盘 近8年有些事情做对了 xff0c 也有更
  • 如何一步一步成为一个领域专家

    经常有人问我 xff0c 为什么有的人工作10年仍然平台无奇 xff0c 而有的人只用3年时间 xff0c 就已经脱颖而出 xff0c 成绩斐然 我说 xff0c 是呀 xff0c 有些参加工作多年却仍然只会复制粘贴简单业务代码 xff0c
  • 如何一步一步建立自己的技术影响力

    很多朋友是不是有这样的经历 xff0c 当我们还是一个菜鸟的时候 xff0c 团队里总有1 2个技术大拿 xff0c 每当有技术问题大家争论不休 xff0c 团队成员讨论的面红耳赤 xff0c 技术大牛实在看不下去 xff0c 掐灭手中的烟
  • 一个老程序员的一些职场经验分享

    有一些关于职场的经验 xff0c 当然有一些是以前总结过的 xff0c 现在归类总结一下 xff0c 上半部分是通用职场 xff0c 下半部分是程序员专用 一 通用职场经验 1 xff09 很多人认为事情做得多 xff0c 事情做得好就能晋
  • 第2章 第一个Spring Boot项目

    开发工具选择 工欲善其事必先利其器 xff0c 我们进行Java项目开发 xff0c 选择一个好的集成开发工具 xff08 IDE xff09 对提高我们的开发调试效率有非常大的帮助 这里我们选择大名鼎鼎的IDEA xff0c 它全称 In
  • 第8章 使用注解的方式整合MyBatis 入门详解

    目录 注解方式和配置文件方式的优缺点 使用注解方式整合MyBatis 添加依赖 配置application properties文件 在启动类上添加apperScan注解 创建mapper接口和实体类目录 添加实体类 测试验证 添加参数 直
  • 第9章 Spring Boot整合JPA 与 JpaRepository 基础方法介绍

    参考文章 xff1a 第1章 Spring Boot到底是什么 xff1f 陈小房的博客 CSDN博客 第2章 第一个Spring Boot项目 陈小房的博客 CSDN博客 第3章 Spring Boot项目配置详解 陈小房的博客 CSDN