04 后端增删改查【小白入门SpringBoot + Vue3】

项目笔记,教学视频来源于B站青戈
https://www.bilibili.com/video/BV1H14y1S7YV

保证前面的都功能都实现后,接着往下走。

查 +分页

接下来,实现前端页面分页功能。

前端分页组件

打开elementplus官网,找到合适的分页组件,其对应代码如下

<template><el-pagination background layout="prev, pager, next" :total="1000" />
</template>

放到前端的表格组件下方,加个div包裹。

js加个变量,因为total总记录数量,应该是从数据库拿到的,是动态的。

<!--    分页组件--><div><el-pagination background layout="prev, pager, next" :total="total" /></div>const total = ref(0) //总记录数,初始为0

然后打开后端项目,实现分页查询,需要与SQL语句配合,而且浏览器的路由也可以修改后缀。

后端SQL语句修改

首先是数据库的SQL语句,复制上个SQL代码,稍加修改,让其实现分页,借助LIMIT这个分页函数后面的两个参数,第一个是开始序号,第二个是每页放置多少条记录。

select * from user where name like%%or date like%%or address like%%or user_no like%%LIMIT 1,2

接着尝试修改后端的SQL代码,

在UserMapper新增SQL代码;

注意@Param在导入包的时候,要选择有apache单词的包,选错会导致报错。

@Select("select * from user where name like concat('%',#{name},'%')  or date like concat('%',#{name},'%') or address like concat('%',#{name},'%') or user_no like concat('%',#{name},'%')  limit #{start}, #{pageSize}") 
List<User> selectPage(@Param("name") String name,@Param("start") Integer start,@Param("pageSize") Integer pageSize); //三个参数

在UserController这个文件添加以下代码

    @GetMapping("/page")    //表示访问到这个函数返回值,其路径是【localhost:9090/user/page】public Result selectPage(@RequestParam String name,@RequestParam Integer start,@RequestParam Integer pageSize){List<User> userList = userMapper.selectPage( name,start,pageSize);return Result.success(userList);}

前端SQL相关修改

后端配置得差不多,前端也进行相应修改,来到HomeView.vue ,把数据请求的路由更改成与后端SQL语句还参数一致的

const load = () =>{request.get('user/page?name=' + input.value + '&start=1&pageSize=2').then(res =>{ // request.get('user/all?name=' + input.value).then(res =>{ //name改成inputconsole.log(res)state.tableData = res.data})
}

然后数据库、前端、后端,都运行,打开前端项目生成的本地网址,若表格出现数据,则这一步成功。

但是上面的分页参数&start=1&pageSize=2,是静态的写死的,我们希望这个分页参数是可以根据用户手动选择的,于是要考虑运用分页组件的参数。

找到elementplus前端分页组件的代码,加上两个数据绑定

原来
<el-pagination  layout="prev, pager, next" :total="total"/>修改
<el-pagination  layout="prev, pager, next" v-model:current-page="pageNum" v-model:page-size="pageSize" :page-size="[1,2,5]" :total="total"/>

在js加上这两个变量,为了把页码的两个参数变成动态的,初步修改如下

const pageNum = ref(1) //页码。最小的是1
const pageSize = ref(1) //页码大小,实际上数据库无记录可以显示零条,但是理论上最起码显示一条const load = () => {let start = pageNum.value - 1  //数据库的记录序号从0开始,但是前端页面数据从1开始request.get('user/page?name=' + input.value + '&start='+ start +'&pageSize=' + pageSize.value).then(res => { //省略代码})
}

去看前端的分页,但是发现没反应。

首先因为组件的total 变量数值默认是 零,但数据库目前的总数量是2,故手动修改。

const total = ref(2) //总记录数

其次,分页没有触发load函数故,回到elementplus官网,找到分页切换触发的两个函数,所以修改如下

原来(其他属性省略没写)<el-pagination layout="prev, pager, next"  / >修改后<el-pagination  layout="sizes,prev, pager, next"  @size-change="load"  @current-change="load"/>

补充:

layout属性有多个属性值,它们有不同的功能,从左到右依次为

  1. total,表示后端数据的总条数,即页面上的 “ 共400条 ”
  2. sizes,表示每页能容纳多少条数据,即页面上的下拉选框 “ 100条/页 ”
  3. prev,表示向前翻一页,即页面上的 “ < ”
  4. pager,表示指定翻到哪一页,即页面上的 “ 1 2 3 4 ”
  5. next,表示向后翻一页,即页面上的 “ > ”
  6. jumper,表示直接跳去哪一页,即页面上的 “ 前往 3 页 ”

二个核心事件

  1. @size-change事件,当你使用下拉选框改变page-size属性时,它能监听到page-size属性的变化,并立刻将最新的值自动传给的事件处理函数,你甚至无需给它手动传参
  2. @current-change事件,当你改变current-page属性时,它能监听到current-page属性的变化,并立刻将最新的值自动传给相应的事件处理函数,你甚至无需给它手动传参

然后,发现,分页组件的文案都是英文,想改成中文,可以使用elementplus的国际化功能。来到前端项目的main.js ,添加下面的代码

import zhCn from 'element-plus/dist/locale/zh-cn.min'// app.use(ElementPlus)  //原来的
app.use(ElementPlus,{  //修改的locale: zhCn,
})

一个新的问题,随着数据库记录数量的增多,发现最后一条记录会被吞掉,原因是数据库页的起始序号计算有问题

原来
const load = () => {let start = pageNum.value - 1  //数据库的记录序号从0开始,但是前端页面数据从1开始//省略代码  
}修改
const load = () => {let start = (pageNum.value - 1)*pageSize.value //数据库的记录序号从0开始,但是前端页面数据从1开始,为了避免吞数据,需要乘每页的数量//省略代码  
}

动态total 修改

下一个问题,total的数值,目前还是静态写死的,为了改成动态的,需要从数据库中查出具体数值并显示到前端上。

第一步,后端项目,在UserMapper文件新增代码(复制粘贴上面的SQL语句,然后修改)如下

@Select("select count(id) from user where name like concat('%',#{name},'%')  or date like concat('%',#{name},'%') or address like concat('%',#{name},'%') or user_no like concat('%',#{name},'%')")  
Integer selectTotal(@Param("name") String name); //一个参数,函数返回值是integer类型

第二步,后端项目,UseController文件,新增代码,主要是增加total这个变量,把数值顺利传递到前端,修改如下

原来
@GetMapping("/page")    //表示访问到这个函数返回值,其路径是【localhost:9090/user/page】
public Result selectPage(@RequestParam String name,@RequestParam Integer start,@RequestParam Integer pageSize){List<User> userList = userMapper.selectPage( name,start,pageSize);return Result.success(userList);
}修改
@GetMapping("/page")    //表示访问到这个函数返回值,其路径是【localhost:9090/user/page】
public Result selectPage(@RequestParam String name,@RequestParam Integer start,@RequestParam Integer pageSize){List<User> userList = userMapper.selectPage( name,start,pageSize);Integer total = userMapper.selectTotal(name);Map<String,Object> map= new HashMap<>();map.put("list",userList);map.put("total",total);return Result.success(map);
}    

然后,重新访问前端页面,发现表格里面的数据没有显示出来。

为什么?因为刚才修改的Controller文件,把返回的数据包裹成map类型(key:value),里面有两个key,如下图,data里面有两个对象,需要进一步访问。
在这里插入图片描述

所以,前端访问data的代码要稍加修改,在前端项目,HomeView.vue修改

原来
<el-pagination layout="sizes,prev, pager, next"/>const load = () => {//省略代码({state.tableData = res.data})
}修改(layout加上total这个布局,展示一共有多少条数据)
<el-pagination layout="sizes,prev, pager, next,total"/>const load = () => {//省略代码({state.tableData = res.data.list  //修改这里total.value = res.data.total  //添加这个语句  })
}

补充说明:layout等号右边的单词,排序也有是有讲究的,会根据你排放的顺序调整哦



刚开始前端的增删改查,都是在前端单方面的简易模拟,接下来与数据库挂钩。

先做增加功能。

增加的数据中,有“日期”信息,之前为了简单,只用了字符串String类型,但是实际上是用专门的日期组件,更加方便美观。

在elementplus找到日期选择器组件,复制粘贴然后根据自身需求修改代码,如下

<el-date-picker v-model="state.form.data" type="date" placeholder="选择一个日期" />

来到后端,把数据库SQL语句写好,来到UseMapper,新增代码如下

@Insert("insert into user(name,date,address,user_no) values( #{name} , #{date} ,#{address},#{userNo}  )")
void insert(User user);

来到UseController,新增代码如下

    @PostMapping("/save")public Result save(@RequestBody User user){userMapper.insert(user);return Result.success();}

至此,后端代码ok,需要修改前端的相应代码。

来到前端项目HomeViews.vue ,修改save()函数

原来
const save = () => {if (globalIndex.value > -1) { //编辑数据state.tableData[globalIndex.value] = state.form;globalIndex = ref(-1)} else { //新增数据// 向表格添加数据state.tableData.push(state.form);}// 关闭弹窗dialogFormVisible.value = false;
}修改
const save = () => {console.log(state.form)//打印当前弹窗的数据内容request.post('/user/save',state.form).then(res=>{if (res.code === '200'){ElMessage.success("保存成功")// 关闭弹窗dialogFormVisible.value = false;}else {ElMessage.error(res.msg)}},err=>{console.log("发送post请求失败:",err)  //现在是后端返回错误})
}

但是运行的时候出现错误,如下

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.example.springboot.entity.User]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.example.springboot.entity.User` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 2]] with root cause

找了师兄才解决这个问题

在后端UseMapper添加三个注解,并且引入相关的包

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor

接着就可以在数据库中查看,数据是否被增加进去。

发现,虽然添加成功了,但是添加的时间格式有问题

在这里插入图片描述

故需要修改时间格式,解决很简单,elementplus有时间格式的属性,修改如下

原来<el-date-pickerv-model="state.form.date"type="date"placeholder="选择日期"/>修改<el-date-pickerv-model="state.form.date"type="date"placeholder="选择日期"value-format="YYYY-MM-DD"/>


下一个功能,修改数据

跟“增加数据”步骤相似

后端项目,修改SQL语句,打开UseMapper,新增下面的代码(一定不能写错变量的名字!!!)

@Update("update user set name = #{name}, date = #{date}, address = #{address} ,user_no = #{userNo} where id = #{id} ")
void update(User user);

然后打开UseController,新增代码如下

    @PutMapping("/update")public Result update(@RequestBody User user){  //函数名原来是saveuserMapper.update(user);return Result.success();}

相应地,前端网络请求也要进行相应修改,来到HomeView.vue

原来
const save = () => {console.log(state.form)request.post('/user/save',state.form).then(res=>{if (res.code === '200'){ElMessage.success("操作成功")// 关闭弹窗dialogFormVisible.value = false;}else {ElMessage.error(res.msg)}},err=>{console.log("发送post请求失败:",err)})
}    修改
const save = () => {console.log(state.form)request({url: state.form.id ? '/user/update':'/user/save',method: state.form.id ? 'PUT' :'POST',data: state.form}).then(res=>{if (res.code === '200'){ElMessage.success("操作成功")dialogFormVisible.value = false}else{ElMessage.error("操作失败", res.msg)}})
}

更新数据操作成功后,发现,虽然数据库的记录更新了,

但是前端页面还没有及时更新,所以调用load()

const save = () => {//省略代码if (res.code === '200'){ElMessage.success("操作成功")dialogFormVisible.value = falseload() //调用查询方法,及时更新数据  }//省略代码
}

补充一个细节,希望新增的记录能够显示在最前面,所以,SQL语句查询的时候,增加一个倒序排序

order by id desc

原来
@Select("select * from user where name like concat('%',#{name},'%')  or date like concat('%',#{name},'%') or address like concat('%',#{name},'%') or user_no like concat('%',#{name},'%') limit #{start}, #{pageSize}") 
List<User> selectPage(@Param("name") String name,@Param("start") Integer start,@Param("pageSize") Integer pageSize); //三个参数,注意相应类型修改
@Select("select * from user where name like concat('%',#{name},'%')  or date like concat('%',#{name},'%') or address like concat('%',#{name},'%') or user_no like concat('%',#{name},'%')  order by desc limit #{start}, #{pageSize}") 
List<User> selectPage(@Param("name") String name,@Param("start") Integer start,@Param("pageSize") Integer pageSize); //三个参数,注意相应类型

后端

UseMapper新增代码

    @Delete("delete from user where id = #{id}")void delete(Integer id);

UseController新增代码

    @DeleteMapping("/del")public Result delete(@RequestParam Integer id){userMapper.delete(id);return Result.success();}

前端HomeView.vue (多余的代码省略了)

原来
<el-button @click.prevent="remove(scope.$index)">删除</el-button>
// 删除数据
const remove = (index) => {// 从index的位置开始,删除一行state.tableData.splice(index, 1)
}修改
<el-button @click.prevent="remove(scope.row.id)">删除</el-button>
// 删除数据
const remove = (id) => {request.delete('user/del?id='+id).then(res=>{if (res.code === '200'){ElMessage.success("操作成功")load() //调用查询方法,及时更新数据}else{ElMessage.error("操作失败", res.msg)}})
}

以上就是小白入门增删改查的基础操作了

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件测试工具常用的都有哪些

软件测试工具是用于辅助软件测试的软件工具&#xff0c;可以帮助测试人员执行测试用例、记录测试结果、跟踪缺陷状态等&#xff0c;提高测试效率和质量。以下是一些常见的软件测试工具&#xff1a; 一、AutoRunner自动化测试工具 AutoRunner(简称AR&#xff09;是国内自主研发…

python使用selenium webDriver时 报错

可能原因和解决&#xff1a; 1. python 解释器 ----> 设置 2. 浏览器版本 与 浏览器驱动版本不一致 ----> 安装同一版本的 (下载chromedriver | 谷歌驱动更高版本的测试版) 参考&#xff1a;Python使用Selenium WebDriver的入门介绍及安装教程-CSDN博客 Selenium安…

企业网盘哪家好?值得信赖的品牌推荐

企业网盘可谓是当下热门的企业服务之一&#xff0c;市面上也出现了非常多企业网盘工具。那么&#xff0c;企业网盘哪家好&#xff1f;哪个品牌更值得信赖呢&#xff1f; 企业网盘哪家好&#xff1f; Zoho Workdrive企业网盘一定榜上有名&#xff0c;Zoho Workdrive企业网盘是著…

IDEA JRebel安装使用教程

1、下载插件 版本列表&#xff1a;https://plugins.jetbrains.com/plugin/4441-jrebel-and-xrebel/versions 下载&#xff1a;JRebel and XRebel 2022.4.1 这里下载2022.4.1版本&#xff0c;因为后续新版本获取凭证会比较麻烦。下载完成会是一个压缩包。 2、安装 选择第一步…

微软Copilot即将对大陆开放,一起来看看都有什么好用的功能

微软发布了Copilot&#xff0c;12月1日起对大陆用户开放&#xff0c;以下是Copilot的11个新功能&#xff0c;你一定不想错过&#xff1a;1. PowerPoint&#xff1a; 将Word文档转换为演示文稿。从文件中快速创建演示文稿。通过关键幻灯片总结冗长的演示文稿。使用提示添加新的…

2024贵州大学计算机考研分析

24计算机考研|上岸指南 贵州大学 贵州大学计算机科学与技术学院&#xff08;贵州大学省级示范性软件学院&#xff09;位于贵州省贵阳市花溪区贵州大学东校区。 计算机科学与技术学院&#xff08;软件学院&#xff09;自1972年创办计算机软件本科专业开始&#xff0c;至今已有…

cadence layout lvs时出现error

Error&#xff1a;Schematic export failed or was cancelled.Please consult the transcript in the viewer window. 解决办法同下&#xff1a; cadence layout lvs时出现error-CSDN博客

Unity 头顶图文字性能优化

如图&#xff1a;常规的排版&#xff0c;会有很多Batches。这是优化后的Batches只有3。 常用解决方案&#xff1a; 1、创建两个Canvas&#xff0c;一个放所有文本Text&#xff0c;一个放所有Image。但这里有会有两个问题&#xff1a;一旦文字夹在两个Image中间&#xff0c;还有…

掌握Katalon Studio 导入 swagger 接口文档,接口测试效率提升100%

katalon studio大家都已经不陌生了&#xff0c;是一款现在非常主流的自动化测试工具&#xff0c;包括了web、api、APP&#xff0c;甚至PC应用程序都可以使用它来完成自动化测试。 swagger是一款RESTFUL接口的文档在线自动生成软件&#xff0c;swagger是一个规范和完整的框架&a…

智能座舱架构与芯片 - (2) 架构篇

一、定义 1.1 智能座舱定义 按照百度百科的定义&#xff0c;智能座舱&#xff08;intelligent cabin&#xff09;旨在集成多种IT和人工智能技术&#xff0c;打造全新的车内一体化数字平台&#xff0c;为驾驶员提供智能体验&#xff0c;促进行车安全。目前国内外已经有很多研究…

算法刷题-动态规划-1

算法刷题-动态规划-1 不同路径不同路径||方法一&#xff1a;方法二 第N个泰波那契数递归写法滚动数组 三步问题递归操作滚动数组 使用最小画法爬楼梯递归 解码方法方法一方法二&#xff1a;&#xff08;大佬讲解&#xff09; 不同路径 //机器人不同的路径进入到指定的地点 publ…

SpringBoot : ch06 整合 web (一)

前言 SpringBoot作为一款优秀的框架&#xff0c;不仅提供了快速开发的能力&#xff0c;同时也提供了丰富的文档和示例&#xff0c;让开发者更加容易上手。在本博客中&#xff0c;我们将介绍如何使用SpringBoot来整合Web应用程序的相关技术&#xff0c;并通过实例代码来演示如何…

“图纸保密大作战:上海迅软DSE解决方案守护机械公司核心资料

机械行业是我国重要的工业制造行业之一&#xff0c;相关企业在发展中往往需要用到ERP、PDM、PLM等系统来对产品信息进行管理&#xff0c;其中便涉及到大量文档和图纸等重要数据。然而随着业务的快速发展和数字化转型&#xff0c;机械行业也面临着如数据泄露、外来袭击攻击、内部…

华为obs上传下载-Java版 2023-11-23

弄了半天&#xff0c;老师帮弄成功了&#xff0c;经过同意&#xff0c;分享到网上&#xff0c;希望能帮助更多人&#xff0c;至于怎么弄的&#xff0c;我也不知道。 创建idea项目后&#xff0c;项目结构&#xff0c;对应文件没有的创一个 pom.xm 注意改Java版本&#xff0c;我…

AIGC前沿技术与数字创新应用合作交流和论坛发布活动圆满落幕

2023年11月17日下午&#xff0c;AIGC前沿技术与数字创新应用合作交流和论坛发布活动在北京市海淀区牡丹科技楼B座B1报告厅成功举办。 在这个以技术为驱动力的时代&#xff0c;AIGC等这些前沿技术正以惊人的速度改变着我们的生活和产业格局。利用新兴技术和数字化工具来解决问题…

vite vue3配置eslint和prettier以及sass

准备 教程 安装eslint 官网 vue-eslint ts-eslint 安装eslint yarn add eslint -D生成配置文件 npx eslint --init安装其他插件 yarn add -D eslint-plugin-import eslint-plugin-vue eslint-plugin-node eslint-plugin-prettier eslint-config-prettier eslint-plugin…

【性能测试】稳定性/并发压力测试的TPS计算+5W并发场景设计...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、稳定性测试TPS…

【MySQL】索引与事务

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文录入于《MySQL》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&a…

局域网内Ubuntu上搭建Git服务器

1.在局域网内选定一台Ubuntu电脑作为Git服务端&#xff1a; (1).新建用户如为fbc&#xff0c;执行如下命令&#xff1a;需设置密码&#xff0c;此为fbc sudo adduser fbc (2).切换到fbc用户&#xff1a;需密码&#xff0c;此前设置为fbc su fbc (3).建一个空目录作为仓…

buildadmin+tp8表格操作(1)----表头上方添加按钮和自定义按钮

buildAdmin 的表头上添加一些按钮&#xff0c;并实现功能 添加按钮 <template><!-- buttons 属性定义了 TableHeader 本身支持的顶部按钮&#xff0c;仅需传递按钮名即可 --><!-- 这里的框架自带的 顶部按钮 分别有 刷新 &#xff0c; 添加&#xff0c; 编辑&…