SpringBoot项目-实现简单的CRUD功能和分页查询

news2024/12/23 1:05:40

背景

本博文主要是创建了一个新的SpringBoot项目,实现基本的增删改查,分页查询,带条件的分页查询功能。是方便初学者学习后端项目的一个比较清晰明了的实践代码,读者可根据博文,从自己动手创建一个新的SpringBoot项目,到使用PostMan测试基本请求,完完全全实践一遍,写出自己的代码,或者实现自己想要的功能。因为在这个过程中会遇到许多的问题,从JDK的版本选择到跑通SpringBoot项目,最后到成功发起一个请求。所以,最好是自己练习一下,最终做到游刃有余。

环境的安装

本次SpringBoot项目主要用到,一是IDEA,二是MYSQL(服务端),三是DBeaver(一个数据库的客户端),四是PostMan(用于发送HTTP请求)。
建议读者先按照MYSQL包,再按照DBeaver, 调通数据库以后,再开始编写项目。

另外就是在一开始建立一个数据库的时候,这里不要写具体的名称。数据库连接以后,再定义具体的数据库名,mydatabase

我们本次的建表语句如下:

-- mydatabase.student_info definition
CREATE TABLE `student_info` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(100) CHARACTER SET utf8mb3 NOT NULL DEFAULT '""',
`address` varchar(100) CHARACTER SET utf8mb3 NOT NULL,
`other` varchar(100) CHARACTER SET utf8mb3 NOT NULL,
`age` int NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=macce;

建好表以后,往表中添加如下示例数据。添加好的表数据如下

创建一个新的SpringBoot项目

1、新建一个project;
这边我们使用maven管理依赖,maven的依赖管理目录可以单独设置一个空目录,自己比较好找到的目录,有时候依赖下载失败,需要从这个目录中删除一些依赖文件;目录的设置可在项目生成以后在IDEA中进行设置。然后jdk的版本有8 就选择8, 没有的话,这里随便选一下,后面编译的时候,可以在IDEA中重新设置。


点击下一步,可以设置SpringBoot的版本。以及要在pom中引入哪些依赖包,方便我们后续写代码的时候调用。我这边简单选了几个,如果还有要使用的依赖,直接勾选就行,或者项目建好后手动在pom添加也可以。
 

,
点击create, 并使用new windows打开,就得到一个新的SpringBoot项目。接下来就等待依赖下载成功,下载成功以后,maven的目录是这样的。本次项目的pom.xml文件如下:

 
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo3</name>
<description>demo3</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

配置文件 application.yml

配置文件中的数据库的用户名和密码都要和你实际进行数据库连接时配置的一样,url也是如此。
server.port: 8088 是tomcat的端口号。
com.mysql.cj.jdbc.Driver是一个驱动类,是MySQL Connector 驱动程序中的 JDBC 驱动类,用于在 Java 应用程序中建立与 MySQL 数据库的连接。 一旦建立了连接,JDBC 驱动类允许 Java 应用程序执行 SQL 查询、更新和其他数据库操作。应用程序可以使用 JDBC API 与数据库进行通信,发送和接收数据。JDBC 驱动类还支持事务管理。Java 应用程序可以使用 JDBC API 开启、提交或回滚事务,确保数据库操作的原子性、一致性、隔离性和持久性(ACID 属性)。在发生错误或异常时,驱动类也会生成适当的异常,应用程序可以捕获并处理这些异常。
加载驱动类是建立连接和执行数据库操作的第一步!
url 指的是数据库连接的 URL,它用于指定要连接的数据库的位置和其他连接参数,localhost指的是本地的主机名,3306是mysql的默认端口号。mydatabase是要连接的数据库的名称。应用程序和数据库通信,首先会通过该url建立连接,不过root和password需要和数据库连接配置中严格一致,否则会连不到数据库。
有关hibernate 的这段配置意味着通过 JPA 和 Hibernate 配置了禁用自动 DDL(Data Definition Language)生成、打印执行的SQL语句到控制台,以及指定了 Hibernate 使用的 MySQL 数据库方言是 MySQL 5 的 InnoDB 存储引擎方言。use_jdbc_metadata_defaults参数当设置为 false 时,Hibernate 将不使用 JDBC 元数据的默认设置。
重点说明一下ddl-auto, 等于none是指Hibernate 不会尝试自动创建、更新或删除数据库表结构。

 
server.port: 8088
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/mydatabase
jpa:
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate:
temp:
use_jdbc_metadata_defaults: false
dialect: org.hibernate.dialect.MySQL5InnoDBDialect

业务代码

在Web后端应用程序中,Controller主要接收来自用户的请求并根据请求调用适当的业务逻辑(Service层),然后将处理结果返回给用户。
总结的说,Controller的作用是:1、接收请求;2、调用Service层的方法;3、参数解析,对请求头中的参数进行解析;4、返回响应结果。将处理结果封装成适当的响应(如HTML页面、JSON数据等)返回给客户端。我这边为了方便起见,直接调repository中的方法了,后续补充一个Service层。
1、先写一个Controller

 
package com.example.demo3.controller;
import com.example.demo3.repository.StudentEntity;
import com.example.demo3.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.List;
@RestController // 注意,该注解表明是是rest风格的API, 返回值通常是数据对象,Spring 将数据转换为JSON或者XML格式,返回给客户端。
// controller返回的是视图名称或者ModelAndView对象。需要配置@ReponseBody使用,即在方法的前面加上这个注解。
@RequestMapping("/student")
public class StudentController {
@Autowired
StudentRepository repository;
//查, 通过姓名查询
@RequestMapping(value = "/byname", method = {RequestMethod.GET})
//@ResponseBody
public List<StudentEntity> findByName(@RequestParam("name") String name) {
return repository.findByName(name);
}
// 全部返回,线上我们一般都用分页查询,因为数据量比较大嘛。直接返回全部数据的接口用的很少或者几乎不用。
@GetMapping(value = "/all")
public List<StudentEntity> findAlls() {
List<StudentEntity> all = repository.findAll();
return all;
}
// 增
@PostMapping(value = "/add")
private String addOne(@RequestBody StudentEntity student){
repository.save(student);
return "学生" + student.getName() + "添加成功";
}
// 改
@PutMapping(value = "/update")
private String updateOne(@RequestBody StudentEntity student){
repository.save(student);
return "学生" + student.getName() + "修改成功";
}
// 删
@DeleteMapping(value = "/delete")
private String deleteOne(@RequestParam("id") Integer id) {
repository.deleteById(id);
return "学生" + id + "删除成功";
}
// 简单分页查询
@GetMapping("/page")
public Page<StudentEntity> findByPage(@RequestParam(value = "page", defaultValue = "0") int page, @RequestParam(value = "size", defaultValue = "2") Integer size) {
Pageable pageable = PageRequest.of(page, size);
return repository.findAll(pageable);
}
// 带条件复杂分页查询
@GetMapping("/page2")
public Page<StudentEntity> findByPage2(@RequestParam(value = "name") String name, @RequestParam(value = "age") Integer age, @RequestParam(value = "page", defaultValue = "0") int page, @RequestParam(value = "size", defaultValue = "2") Integer size) {
Pageable pageable = PageRequest.of(page, size);
Specification<StudentEntity> specification = prediacte(name, age);
return repository.findAll(specification, pageable);
}
public static Specification<StudentEntity> prediacte(String name, Integer age) {
return (Root<StudentEntity> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) -> {
// 这边简单用name和age查询一下
Predicate namePredicate = criteriaBuilder.equal(root.get("name"), name);
Predicate agePredicate = criteriaBuilder.equal(root.get("age"), age);
return criteriaBuilder.and(namePredicate, agePredicate);
};
}
}

2、Repository
这个是dao层,主要是执行一些和数据库交互的功能。在和数据库交互的时候,我们要创建一个实体类Entity, 这边我们叫做StudentEntity实体对象,相应的,数据库里面也应该有和这个实体类一一映射的表。数据库中的表名就可以写在注解@Table里。
@Entity注解的作用如下。首先, @Entity的含义是用于标识一个java类作为JPA(java persistence api)实体类, 表示该类将映射到数据库中的表。也就是说,实体类和数据库表的映射关系由该注解的实现,其中的映射关系具体体现在:实体类的属性和数据库表的字段一一对应。
@id注解用于表示某个字段作为表的主键,每个表必须要显式定义一个主键。
@Column 注解是 JPA(Java Persistence API)中用于描述实体属性与数据库表列之间映射关系的注解。通过 @Column 注解,可以指定实体类属性与数据库表中列的映射细节,如列名、数据类型、长度、是否可为空等。即可以更精细地控制实体属性与数据库表列的映射关系。如代码所示,name中指定的列名和表中的对应起来,然后private 属性就可以任意取一个名字了,不过建议还是都对应起来。
StudentEntity

 
package com.example.demo3.repository;
import lombok.Data;
import javax.persistence.*;
@Entity
@Table(name = "student_info")
@Data
public class StudentEntity {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name = "name")
private String name;
@Column(name = "age")
private int age;
@Column(name = "address")
private String address;
@Column(name = "other")
private String other;
}

以下是StudentRepository类,这边定义的几个方法都是直接调用Spring JPA 封装好的方法,可直接调用。如果遇到比较复杂的场景,我们也可以在这里写一个接口,再写接口方法的具体实现。

 
package com.example.demo3.repository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
public interface StudentRepository extends JpaRepository<StudentEntity, Integer>, JpaSpecificationExecutor<StudentEntity> {
List<StudentEntity> findByName(String name);
List<StudentEntity> findAll();
void deleteById(Integer id);
Page<StudentEntity> findAll(Pageable pageable);
}

测试结果

有两种测试方法,可以在网页端直接输入url发起HTTP请求,由于我们的HTTP请求中要使用对象,所以选择Postman会比较方便。
1、根据name查询
 


2、增加一个student
 


3、修改id=xx的学生的信息
 


4、删除id=xx的学生信息
 


5、分页查询

 
我们默认的是取第0页的数据,每页取size个数据。 故"pageSize": 2,"pageNumber": 0。 totalPages指的是总共有多少条数据, "totalPages": 3指的是一共要分多少页。5条数据,每页2个数据,那么就是分3页。"sort"是分页时排序的属性。
{
"content": [
{
"id": 1,
"name": "小红",
"age": 18,
"address": "深圳市",
"other": "女;本科毕业,程序员"
},
{
"id": 2,
"name": "小黑",
"age": 29,
"address": "广州市",
"other": "男;本科毕业,程序员"
}
],
"pageable": {
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageSize": 2,
"pageNumber": 0,
"paged": true,
"unpaged": false
},
"totalElements": 5,
"last": false,
"totalPages": 3,
"number": 0,
"size": 2,
"sort": {
"empty": true,
"sorted": false,
"unsorted": true
},
"numberOfElements": 2,
"first": true,
"empty": false
}

6、带条件的分页查询

{
    "content": [
        {
            "id": 2,
            "name": "小黑",
            "age": 29,
            "address": "广州市",
            "other": "男;本科毕业,程序员"
        }
    ],
    "pageable": {
        "sort": {
            "empty": true,
            "sorted": false,
            "unsorted": true
        },
        "offset": 0,
        "pageNumber": 0,
        "pageSize": 2,
        "unpaged": false,
        "paged": true
    },
    "last": true,
    "totalPages": 1,
    "totalElements": 1,
    "number": 0,
    "size": 2,
    "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
    },
    "numberOfElements": 1,
    "first": true,
    "empty": false
}

后面我会加一个Service层。今天就先写这么多吧。

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

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

相关文章

Scratch教师节 —— 感恩教师节

小虎鲸Scratch资源站-免费Scratch作品源码,素材,教程分享平台! Scratch教师节动画作品——感恩教师节 在这个特别的日子里&#xff0c;我们迎来了教师节。为了表达对老师们的感激之情&#xff0c;Scratch平台上的小朋友们用创意与热情制作了精彩的动画作品——“感恩教师节”。…

在国产芯片上实现YOLOv5/v8图像AI识别-【4.3】RK3588使用yolov8+bytetrack实现跟踪更多内容见视频

本专栏主要是提供一种国产化图像识别的解决方案&#xff0c;专栏中实现了YOLOv5/v8在国产化芯片上的使用部署&#xff0c;并可以实现网页端实时查看。根据自己的具体需求可以直接产品化部署使用。 B站配套视频&#xff1a;https://www.bilibili.com/video/BV1or421T74f 背景…

【Canvas与艺术】四叶花

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>386.四叶花</title><style type"text/css">.c…

GDB watch starti i files

watch break starti 在程序的最初开始运行的位置处断下来 ​​ i files 查看程序及加载的 so 的 sections ​​

【Ubuntu】环境准备

平时不怎么接触运维。linux的东西都快忘完了&#xff0c;正好最近腾讯云优惠&#xff0c;38元一年&#xff0c;优惠拉满&#xff0c;拿下一个玩一玩&#xff0c;可以当小程序的服务器&#xff0c;记录一些常用的操作&#xff0c;省的每次用的时候都想不起来 1.有一个linux系统…

对接后端download接口报未知异常错误

你一定遇到过这种情况&#xff0c;在一个项目中下载功能明明好好的&#xff0c;下载接口调用方法与前端调用方法封装的好好的&#xff0c;可是换了一个接口&#xff0c;竟然搞罢工了&#xff0c;类似下面这样的&#xff0c;你会不会无从下手&#xff0c;不知道该怎么办呢&#…

2.C_数据结构_线性表

线性表的描述 线性表就是若干数据的一个线性序列。 数学表达式&#xff1a; L&#xff1a;表名 a0~an-1&#xff1a;数据元素 n&#xff1a;表长&#xff0c;n>0是为非空表 二元描述形式&#xff1a; D&#xff1a;数据元素D用 ai 表示&#xff0c;这个 i 范围是0~n-1 …

【C++从练气到飞升】21---再谈哈希算法:位图 | 布隆过滤器 | 哈希切分

&#x1f388;个人主页&#xff1a;库库的里昂 ✨收录专栏&#xff1a;C从练气到飞升 &#x1f389;鸟欲高飞先振翅&#xff0c;人求上进先读书&#x1f389; 目录 ⛳️推荐 一、位图 1.1 一道面试题 1.2 位图的概念 1.3 位图的模拟实现 1.4 位图的应用 1.4.1 给定100亿…

双项第一!鼎捷强势领跑PLM市场

近日&#xff0c;国际数据公司IDC发布了《中国PLM市场分析及厂商份额&#xff0c;2023&#xff1a;创新左移》 报告数据显示鼎捷PLM2023年收入增长率39.5%&#xff0c;收入增速市场第一 鼎捷在多个细分行业市场中保持领先&#xff0c;在装备制造PLM领域市场份额达到7.9%市占率…

基于 rt-thread的I2C操作EEPROM(AT24C02)

一、AT24C02 The AT24C01A/02/04/08A/16A provides 1024/2048/4096/8192/16384 bits of serial electrically erasable and programmable read-only memory (EEPROM) organized as 128/256/512/1024/2048 words of 8 bits each.AT24C01A/02/04/08A/16A提供1024/2048/4096/8192…

Redis进阶(三)--Redis高性能底层原理

文章目录 第三章、Redis高性能底层原理一、持久化1、RDB&#xff08;1&#xff09;给哪些内存数据做快照?&#xff08;2&#xff09;RDB文件的生成是否会阻塞主线程&#xff08;3&#xff09;bgsave执的行流程&#xff08;4&#xff09;RDB文件&#xff08;5&#xff09;RDB的…

ios免签H5

1、windows下载mobileconfig文件制作工具&#xff0c;可在csdn搜索iPhone_Mobileconfig_Tool下载安装&#xff1b;IOS 从APP Store 下载Apple Configurator 2 2、用申请的域名SSL证书给mobieconfig文件签名&#xff0c;最好下载Apache证书&#xff0c;里面包含 AE86211.crt…

zabbix-高级应用(主被动监控、邮件告警、企业微信告警)

文章目录 zabbix-高级应用监控路由器交换机SNMP简单网络管理协议测试案例配置网络设备创建主机创建监控项测试监控项 自动发现什么是自动发现Discovery&#xff1f;配置自动发现1、创建自动发现规则2、创建Action动作&#xff08;发现主机后自动执行什么动作&#xff09;3、通过…

Python画笔案例-037 绘制彩色格子台阶

1、绘制彩色格子台阶 通过 python 的turtle 库绘制彩色格子台阶&#xff0c;如下图&#xff1a; 2、实现代码 绘制彩色格子台阶&#xff0c;以下为实现代码&#xff1a; """彩色格子台阶.py """ import turtle from random import randomturtle…

小杨做题c++

题目描述 为了准备考试&#xff0c;小杨每天都要做题。第1天&#xff0c;小杨做了a道题;第2天&#xff0c;小杨做了b道题;从第3天起&#xff0c;小杨每天做的题目数量是前两天的总和。 此外&#xff0c;小杨还规定&#xff0c;当自己某一天做了大于或等于m题时&#xff0c;接下…

KRTSt内嵌Lua脚本

KRTSt内嵌Lua脚本 Lua 简介 Lua是一门强大、高效、轻量、可嵌入的脚本语言。它支持多种编程架构&#xff1a;过程编程、面向对象编程&#xff08;OOP&#xff09;、函数式编程、数据驱动编程及数据描述。 Lua结合了简洁的过程语法和强大的数据描述结构&#xff08;基于关联数…

什么是网络准入控制系统?网络准入控制系统七大品牌介绍!

在当今信息化时代&#xff0c;企业网络安全面临着前所未有的挑战。网络准入控制系统&#xff08;NAC, Network Access Control&#xff09;作为一种重要的网络安全技术&#xff0c;扮演着守护企业网络安全大门的关键角色。网络准入控制系统通过对接入网络的设备进行身份验证、安…

为什么现在不建议去电力设计院?终于有人把电力设计院说清楚了!

作者&#xff1a;电气哥 最近电气哥收到了许多面临就业的同学特别是硕士同学有关于电力设计院的咨询&#xff0c;那么现在电力设计院到底还值不值得去&#xff1f;电气哥带你来分析一下电力设计院的前世今生。 01 电力设计院的前世今生 曾经&#xff0c;在我国的大基建时代&…

java设计模式--(行为型模式:策略模式、命令模式、责任链模式)

6&#xff0c;行为型模式 行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务&#xff0c;它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象行为模式&#xff0c;前者采用继承…

keepalived和lvs高可用集群

keepavlied和lvs高可用集群搭建 主备模式&#xff1a; 关闭防火墙和selinux systemctl stop firewalld setenforce 0部署master负载调度服务器 zyj86 安装ipvsadm keepalived yum install -y keepalived ipvsadm修改主节点配置 vim /etc/keepalived/keepalived.conf! Conf…