当前位置: 首页 > news >正文

【图书管理系统】深入解析基于 MyBatis 数据持久化操作:全栈开发图书管理系统:查询图书属性接口(注解实现)、修改图书属性接口(XML 实现)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


查询图书属性接口


约定前后端交互接口


约定前后端交互接口,进入修改页面,需要显示当前图书的信息;

请求  
/book/queryBookById?bookId=25  参数  
无  响应  
{  "id": 25,  "bookName": "图书21",  "author": "作者2",  "count": 999,  "price": 222.00,  "publish": "出版社1",  "status": 2,  "statusCN": null,  "createTime": "2023-09-04T04:01:27.000+00:00",  "updateTime": "2023-09-05T03:37:03.000+00:00"  
}

根据图书ID,获取当前图书的信息。


实现服务器代码


控制层 BookController


image-20250410184907710


业务层 BookService


image-20250410191653924


数据层 BookInfoMapper


根据图书ID,查询图书信息。

@Select("select id, book_name, author, count, price, publish, `status`, 
create_time, update_time " +
"from book_info where id=#{bookId} and status<>0")
BookInfo queryBookById(Integer bookId);

image-20250410185255703


接口测试


重新运行程序,打开页面127.0.0.1:9090/book/queryBookById?bookId=5

image-20250410195011815


修改图书属性接口


约定前后端交互接口


点击修改按钮,修改图书信息。

请求  
/book/updateBook  
Content-Type: application/x-www-form-urlencoded; charset=UTF-8  参数  
id=1&bookName=图书1&author=作者1&count=23&price=36&publish=出版社1&status=1  响应  
""  // 失败信息, 成功时返回空字符串

我们约定,浏览器给服务器发送一个 /book/updateBook 这样的 HTTP 请求,form表单的形式来提交数据;

服务器返回处理结果,返回""表示添加图书成功,否则,返回失败信息。


实现服务器代码


控制层 BookController


image-20250410190019780


image-20250410190115282


业务层 BookService


image-20250410190220780


数据层 BookInfoMapper


更新逻辑相对较为复杂,因为一本书不是每个属性都需要进行修改的;

所以 bookInfo 对象的哪些属性传递了值,我们就更新哪些值,需要使用动态SQL

对于初学者而言,注解的方式拼接动态SQL不太友好,煮啵采用xml的方式来实现。

因为注解和 XML 可以同时在一个 interface 中共存,所以煮啵就不创建新接口了;

image-20250410191823774


添加依赖和配置 XML 路径


配置 xml 路径:

mybatis:mapper-locations: classpath:mapper/**Mapper.xml

最终整体的 yml 配置文件为:

image-20250410192815280


xml 实现:


创建BookInfoMapper.xml文件,并初始化

image-20250410193242524


image-20250410193451978


image-20250410193645225


image-20250410194420971


接口测试


重新运行程序:

image-20250410195937320


结果层层筛查和尝试,煮啵才锁定问题:

image-20250410203205409


查看以前的博客,煮啵发现:spring 和 mybatis 是同级别的层次,煮啵把 mybatis 设置成了 spring 的小弟

image-20250410203129976


修改好代码之后,重新提供 Postman 构造请求,终于成功返回响应:

image-20250410202945566


提前开香槟,我们这一路走来不容易,多少次流着泪说不分离~~~(bushi)

验证数据库表信息是否被修改:

image-20250410203527722


image-20250410203906040


查找、修改图书客户端代码实现


查找图书


我们希望点击修改按钮时:

image-20250410204058159


跳转的输入框中有原来的值:

image-20250410204211566


修改好数据后,点击确认按钮,会调用后端:

image-20250410204514420


接下来,我们来写前端代码:

我们希望,点击修改页面后,马上调用后端,补全输入框中的信息:

image-20250411094913737


点击修改按钮之后,我们看到 URL 中 bookId 的赋值是未被定义的参数:

image-20250411095056902


按修改按钮时,会跳转页面,但是跳转的 URL 参数 bookId 赋值是 book.bookId ,与后端属性名 id 不同,自然无法识别 bookId:

image-20250411095310336


image-20250411095836316


image-20250411095544257


修复好 book_list 跳转 book_update 的 URL 参数后,我们继续补齐 book_update 的 ajax 请求:

image-20250411100206703

location.search 是 JavaScript 中 window.location 对象的一个属性,它返回 URL 中从问号 ? 开始的部分(包括问号),也就是查询字符串部分。

例如:

  • 如果当前 URL 是 http://example.com/book_update.html?bookId=123
  • 那么 location.search 的值就是 "?bookId=123"

在你的代码中:

$.ajax({type: "get",url: "/book.queryBookId" + location.search,
});

这意味着:

  1. 当用户从图书列表点击"修改"按钮时,会跳转到 book_update.html?bookId=123(假设图书ID是123)
  2. 在修改页面,location.search 就是 "?bookId=123"
  3. 这个查询字符串会直接附加到请求URL后面,形成完整的请求:/book.queryBookId?bookId=123

为什么不用传data给后端了?


GET请求中,数据通常是通过URL的查询字符串传递的(就像这里做的),而不是像POST请求那样放在请求体中。这是因为:

  1. GET请求的设计初衷就是用于获取数据,其参数直接体现在URL中
  2. 查询字符串 ?bookId=123 本身就是传递给后端的数据
  3. 这种方式更符合RESTful风格,URL本身就标识了要操作的资源

所以在这种情况下,不需要额外使用data参数来传递数据,因为数据已经包含在URL的查询字符串中了。


我们通过 URL 中的信息,想后端发送 get 请求,接下来就通过 success 接收后端的返回结果,并且通过 id 选择器,对前端输入框对应的属性赋值,赋的值是后端对应的属性:

image-20250411101252726


image-20250411102157181


这里需要注意:图书状态的 value = “1” ,“2” ,是与我们后端数据库的定义有关的,要和后端的枚举对应上:

image-20250411102018303


修改图书


我们观察,在列表页时,我们已经补充了[修改]的链接:

image-20250411121906382


image-20250411102924323


补全修改图书的方法:

通过 id 选择器选中 form 表单,使用 serialize() 对表单进行序列化,就拿到了 fom 表单的值,这样就不需要对 bookName,bookAuthor 这些属性分别赋值

image-20250411103335414


对后端返回的数据进行处理:

image-20250411103656468


接口测试


ctrl+s 保存代码,重新运行程序,结果发现输入框并没有值:

image-20250411111310966


通过 deepseek 不断缩小问题范围,最终锁定 bug:

image-20250411111431688


修改 URL ,保存代码,重新运行程序:

image-20250411111943731


此时点击修改按钮,跳转页面的输入框中有值了:

image-20250411112032814


我们试着修改值:

image-20250411112209408


修改数据,点击确定后,页面跳转到图书列表的第一页:

image-20250411112302631


找到原来的那本书,发现又出 bug 了,对应的属性没有更新:

image-20250411112410258


遇到这种问题,我们要先冷静下来,因为后端打印有日志,方便排查问题,所以我们先看后端,再看前端;

找到对应 update 的日志:

image-20250411112719412

我们发现 SQL 对应的 id 赋值为 null,很幸运的找到了出现问题的原因!


我们再仔细看这条日志,发现前端传过来的 id 值为 null,就说明问题出在前端:

image-20250411112901601


image-20250411113354606

我们修改图书信息,是根据图书ID来修改的,所以需要前端传递的参数中,包含图书ID。

有两种方式:

  1. 获取url中参数的值(比较复杂,需要拆分url)
  2. 在form表单中,再增加一个隐藏输入框,存储图书ID,随 $(“#updateBook”).serialize() 一起提交到后端。

我们采用第二种方式:

在form表单中,添加隐藏输入框。


  • hidden类型的<input>元素。
  • 隐藏表单,用户不可见、不可改的数据,在用户提交表单时,这些数据会一并发送出。
  • 使用场景:正被请求或编辑的内容的ID。这些隐藏的input元素在渲染完成的页面中完全不可见,且没有方法可以使它重新变为可见。

image-20250411113208570


image-20250411113557224


保存代码,重新运行程序,执行上述修改步骤:

image-20250411113724477


image-20250411113749491


在这里插入图片描述

在这里插入图片描述


http://www.mrgr.cn/news/97911.html

相关文章:

  • 用最简单的方式讲述离散傅里叶级数(DFS)以及离散傅立叶变换(DFT)
  • 微服务多模块构建feign项目过程与一些报错(2025详细版)
  • 蓝桥杯 C/C++ 组历届真题合集速刷(一)
  • SmolVLM2: The Smollest Video Model Ever(三)
  • 【数据结构 · 初阶】- 单链表
  • mysql-锁的算法(记录锁、间隙锁、临键锁)
  • LeetCode算法题(Go语言实现)_38
  • Spring事务系列 三
  • 44、Spring Boot 详细讲义(一)
  • wsl2+ubuntu22.04安装blender教程(详细教程)
  • 解决 vite.config.ts 引入scss 预处理报错
  • Adaptive AUTOSAR 状态管理和转换——ActionItemList
  • 【C++游戏引擎开发】第13篇:光照模型与Phong基础实现
  • 1200 模拟量输入输出功能
  • python调用本地部署的大模型(llama3.2)
  • Vue3 + TypeScript 的 Hooks 实用示例
  • XTG900P可编程网关在焦化厂数据采集的应用
  • 编译freecad
  • xHCI 上 USB 读写分析
  • openharmony—release—4.1开源鸿蒙源码编译踩坑记录