【圖書管理系統】深入解析基于 MyBatis 數據持久化操作:全棧開發圖書管理系統獲取圖書列表接口(后端:計算圖書頁數、查詢當前頁展示的書籍)

在這里插入圖片描述

在這里插入圖片描述

在這里插入圖片描述


圖書列表


實現服務器代碼(計算圖書總數量+查詢當前頁需要展示的書籍)


后端響應時,需要響應給前端的數據

  • records:第 pageNum 頁要展示的圖書有哪些(存儲到List集合中)
  • total:計算一共有多少本書(用于告訴前端顯示多少頁)

image-20250408224403942

我們創建一個類 ResponseResult ,用于存放后端計算的 records,total,并且返回前端;

圍繞著這兩個功能,來完善我們的服務端代碼;


控制層 BookController


image-20250408212938351


為了可復用性,我們引入泛型(修改一個類名):

image-20250408213834468


寫好框架之后,我們在 Controller 層先調用這個接口:

image-20250408213906136


對于接口參數,如果參數個數比較多,還是建議直接以對象作為參數:

image-20250408214134584


我們給這兩個屬性先加上一個默認值:

image-20250408214355246


數據層:BookInfoMapper


查詢第1頁的SQL語句

select * from book_info where `status` != 0 limit 0,10;

image-20250408211303566


查詢第2頁的SQL語句

select * from book_info where `status` != 0 limit 10,10;

image-20250408211433468


查詢第3頁的SQL語句

select * from book_info where `status` != 0 limit 20,10;

image-20250408211510253

觀察以上SQL語句,發現:開始索引(offset)一直在改變,每頁顯示條數(limit)是固定的

select * from book_info where status != 0 limit `offset`, `limit`;

開始索引的計算公式:開始索引 = (當前頁碼 - 1) * 每頁顯示條數


接下來,我們實現**對列表翻頁時,查詢第 PageNum 頁的圖書列表** 的功能:

image-20250408215519228


我們還需要計算出 offset 的值,不妨在 PageRequest 類中再增加一個屬性:

image-20250408215859573


并且,我們可以直接在這個類中重寫 offset 的 getter() 方法,也就是在 PageRequest 類中,直接計算出 offset 的值,并且可以在其他類獲取到這個值:

image-20250408220230778


image-20250408220535082


image-20250408220639529


在 PageRequest 中并沒有 limt 屬性,所以我們修改一下 SQL 參數,避免出現 MyBatis 反射異常

image-20250409093749258

通過以上操作,我們就實現了第一個功能:第 pageNum 頁要展示的圖書有哪些


接下來,我們實現第二個功能:計算一共有多少本書

插入數據后,我們使用聚合函數 count 計算一下數據庫中有多少條記錄:

image-20250408210657988


接下來,我們回憶 BookInfo 中 status 屬性的定義(0 - 無效,1 - 可借閱,2 - 不可借閱),因此,我們要先查詢有效的書籍(status != 0):

image-20250408211117125

我們這里有26條數據,如果一頁展示十條記錄,那么26條記錄,就需要三頁;


image-20250408222912122


業務層 BookService


image-20250408223726591


計算出書的數量和當前頁要展示的書后,接下來,識別展示圖書的 status,轉換為中文說明 statusCN:

image-20250408224152991


處理好 statusCN 后,我們根據方法返回類型 ResponseResult<BookInfo> ,設置好返回的書籍數量和當前頁展示的書籍列表:

image-20250408224540754


image-20250408224914348


引入@AllArgsConstructor、 @NoArgsConstructor簡化代碼


這篇博客的5(2)有詳細的 lombok 及相關注解的使用說明,包含 @AllArgsConstructor、 @NoArgsConstructor 的使用說明

image-20250408225249103


image-20250408225410291


引入枚舉類 Enums 簡化代碼


這樣的寫法其實是有點啰嗦的,status 的狀態只有(0,1,2)三種,因此,我們可以使用枚舉類簡化一下上面的代碼:

image-20250409085625718


image-20250409090330756


image-20250409090753624


通過上面的封裝和注解的巧用,我們的 BookService 代碼變得更加精簡了:

image-20250409091308254


總結:

需求/問題描述解決方案技術實現說明
翻頁信息需要返回數據總數列表需要執行兩次SQL查詢1. 第一次查詢總數SELECT COUNT(*)
2. 第二次查詢分頁數據LIMIT語句)
圖書狀態數據庫status 字段映射使用枚舉類處理狀態碼映射關系定義枚舉類狀態碼(如0,1,2)文字描述(如"可借閱",“已借出”)綁定
狀態碼變動導致多處代碼修改通過枚舉類集中管理狀態碼修改時只需調整枚舉類,無需全局搜索替換代碼

image-20250409092430335


測試接口


啟動服務,訪問后端程序:


http://127.0.0.1:9090/book/getListByPage 返回1-10條記錄(按id降序)

image-20250409093945645


http://127.0.0.1:9090/book/getListByPage?currentPage=2 返回11-20條記錄

image-20250409094045394


后端思維導圖梳理


在這里插入圖片描述


實現客戶端代碼


在這里插入圖片描述


ResponseResult 類中添加 private PageRequest pageRequest 屬性的主要目的是實現分頁信息的完整閉環傳遞,具體作用包括:

在這里插入圖片描述

  1. 前端狀態保持
    • 讓前端知道當前返回的數據是依據哪些分頁參數查詢的
    • 避免前端在接收數據后丟失原始的分頁請求參數

  1. 分頁上下文傳遞
    • 當前頁碼(currentPage)
    • 每頁條數(pageSize)
    • 從第幾本書開始展示(offset)

在這里插入圖片描述


  1. 擴展性考慮
    • 方便后續添加排序字段等擴展參數
    • 為前端提供生成分頁控件所需的完整信息

在這里插入圖片描述


在這里插入圖片描述

onPageChange:回調函數,當換頁時觸發(包括初始化第一頁的時候),會傳入兩個參數:

  • 1、"目標頁"的頁碼,Number類型
  • 2、觸發類型,可能的值:“init”(初始化),“change”(點擊分頁)

在這里插入圖片描述


測試接口


ctrl+s 保存前端代碼,重新允許程序,訪問登錄頁面 http://127.0.0.1:9090/login.html

在這里插入圖片描述


登錄后,跳轉到圖書列表第一頁:

在這里插入圖片描述


點擊頁碼,頁面信息得到正確的處理

image-20250408124057586


按 F12 打開控制臺,查看報錯信息:

在這里插入圖片描述


在這里插入圖片描述


保存代碼,重新運行程序,打開頁面:

在這里插入圖片描述


翻頁試試效果:

在這里插入圖片描述


完整服務器代碼


PageRequest

package com.bit.book.model;import lombok.Data;@Data
public class PageRequest {private Integer currentPage = 1;private Integer pageSize = 10;private Integer offset;public Integer getOffset() {return (currentPage-1)*pageSize;}
}

ResponseResult

package com.bit.book.model;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;@AllArgsConstructor
@NoArgsConstructor
@Data
public class ResponseResult<T> {private Integer total;    // 所查詢到的數據列表(存儲到List集合中)private List<T> records;  // 總記錄數(用于告訴前端顯示多少頁)private PageRequest pageRequest;}

BookController

package com.bit.book.Controller;import com.bit.book.model.BookInfo;
import com.bit.book.model.PageRequest;
import com.bit.book.model.ResponseResult;
import com.bit.book.service.BookService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/book")
@Slf4j
public class BookController {@Autowiredprivate BookService bookService;// 返回頁數接口@RequestMapping("/getListByPage")public ResponseResult<BookInfo> getListByPage(PageRequest pageRequest){// 參數校驗, 此處涉及復雜的校驗邏輯,由公司負責安全的團隊負責,這里就省略了// 接收前端發送的請求,調用底層處理請求ResponseResult<BookInfo> listByPage = bookService.getListByPage(pageRequest);// 接收 service 處理好的響應,并返回給前端return listByPage;}
}

BookService

package com.bit.book.service;import com.bit.book.enums.BookStatusEnum;
import com.bit.book.mapper.BookMapper;
import com.bit.book.model.BookInfo;
import com.bit.book.model.PageRequest;
import com.bit.book.model.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class BookService {@Autowiredprivate BookMapper bookMapper;public ResponseResult<BookInfo> getListByPage(PageRequest pageRequest){// 1. 獲取總的圖書數Integer count = bookMapper.count();// 2. 獲取當前頁需要展示的圖書有哪些List<BookInfo> bookInfos = bookMapper.selectBooksByPage(pageRequest);// 3. 識別展示圖書的 status, 轉換為中文說明 statusCNfor (BookInfo bookInfo : bookInfos) {bookInfo.setStatusCN(BookStatusEnum.getStatusByCode(bookInfo.getStatus()).getDesc());}return new ResponseResult<>(count,bookInfos,pageRequest);}
}

BookStatusEnum

package com.bit.book.enums;public enum BookStatusEnum {DELETED(0, "該圖書不存在"),NORMAL(1,"允許借閱"),FORBIDDEN(2,"不允許借閱");private Integer code;private String desc;public static BookStatusEnum getStatusByCode(Integer code){switch (code){case 0: return BookStatusEnum.DELETED;case 1: return BookStatusEnum.NORMAL;case 2: return  BookStatusEnum.FORBIDDEN;default:return null;}}BookStatusEnum(Integer code, String desc) {this.code = code;this.desc = desc;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}
}

BookMapper

package com.bit.book.mapper;import com.bit.book.model.BookInfo;
import com.bit.book.model.PageRequest;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper
public interface BookMapper {@Insert("insert into book_info " +"(book_name, author, count, price, publish, `status`) " +"values (#{bookName}, #{author}, #{count}, #{price}, #{publish}, #{status})")Integer addBook(BookInfo bookInfo);@Select("select * from book_info " +"where `status` !=0 " +"limit #{offset}, #{pageSize}")List<BookInfo> selectBooksByPage(PageRequest pageRequest);@Select("select count(1) " +"from book_info " +"where `status` != 0")Integer count();
}

在這里插入圖片描述

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/76442.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/76442.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/76442.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何在idea中快速搭建一個Spring Boot項目?

文章目錄 前言1、創建項目名稱2、勾選需要的依賴3、在setting中檢查maven4、編寫數據源5、開啟熱啟動&#xff08;熱部署&#xff09;結語 前言 Spring Boot 憑借其便捷的開發特性&#xff0c;極大提升了開發效率&#xff0c;為 Java 開發工作帶來諸多便利。許多大伙伴希望快速…

制作前的關鍵籌備:考試考核系統之核心要點

明確系統使用目的? 制作考試考核系統前&#xff0c;企業需明確系統使用目的&#xff0c;這是開發基石&#xff0c;不同目的決定系統功能特性。用于員工培訓考核時&#xff0c;系統要與培訓內容結合&#xff0c;能生成相應考題&#xff0c;檢驗員工知識掌握程度&#xff0c;具備…

Springboot把外部jar包打包進最終的jar包,并實現上傳服務器

1、創建lib目錄&#xff0c;把jar包放進這個目錄下&#xff0c;然后標記lib目錄為“資源根路徑”&#xff08;鼠標右鍵lib目錄->將目錄標記為->資源根路徑。之后lib文件夾會有如下的圖標變化&#xff09; 文件結構如下&#xff1a; 2、pom文件添加依賴 <dependency…

內容中臺的核心架構是什么?

數據中樞與服務API架構 在內容中臺的核心架構中&#xff0c;數據中樞作為基礎層&#xff0c;通過統一的數據模型與標準化接口&#xff0c;實現多源內容的集中存儲與治理。其核心能力體現在對結構化與非結構化數據的清洗、分類及跨系統同步&#xff0c;例如整合企業內部的CRM、…

Light RPC:一款輕量高效的Java RPC框架實踐指南

Light RPC&#xff1a;一款輕量高效的Java RPC框架實踐指南 一、框架簡介二、快速入門1. 環境準備2. 服務端配置2.1 添加依賴2.2 YAML配置2.3 接口與實現 3. 客戶端配置3.1 添加依賴3.2 YAML配置3.3 客戶端調用 三、核心設計解析四、適用場景與優勢對比五、總結 一、框架簡介 …

Hologres實時數倉在B站游戲的建設與實踐

一、背景 實時數據倉庫是近年來數據技術領域內的一大發展潮流。構建一個能夠實現高吞吐量寫入與更新、端到端全鏈路實時處理以及低延遲、高并發的實時數據倉庫&#xff0c;一直是眾多企業面臨的重大挑戰。隨著B站游戲業務的快速發展&#xff0c;對數據的實時應用需求也日益增加…

Android WiFi協議之P2P介紹與實踐

Android WiFi P2P WiFi P2P (Peer-to-Peer) 是 Android 提供的一種允許設備之間直接通過 WiFi 進行通信的技術&#xff0c;無需接入傳統的 WiFi 網絡或互聯網。這種技術也被稱為 WiFi Direct。 一、WiFi P2P 基本概念 1. 核心組件 P2P 設備&#xff1a;支持 WiFi P2P 的 And…

淺談在HTTP中GET與POST的區別

從 HTTP 報文來看&#xff1a; GET請求方式將請求信息放在 URL 后面&#xff0c;請求信息和 URL 之間以 &#xff1f;隔開&#xff0c;請求信息的格式為鍵值對&#xff0c;這種請求方式將請求信息直接暴露在 URL 中&#xff0c;安全性比較低。另外從報文結構上來看&#xff0c…

若依微服務集成Flowable仿釘釘工作流

項目簡介 本項目工作流模塊集成在若依項目單獨一個模塊&#xff0c;可實現單獨運行部署&#xff0c; 前端采用微前端&#xff0c;嵌入在若依的前端項目中。因博主是后端開發&#xff0c;對前端不是太屬性&#xff0c;沒將工作流模塊前端代碼移到若依前端。下面貼上代碼工程結構…

WPS JS宏編程教程(從基礎到進階)-- 第六部分:JS集合與映射在 WPS 的應用

目錄 第6章 JS集合與映射在 WPS 的應用6-1 集合的創建(實例:唯一值提取)示例代碼詳細解析Excel 環境模擬說明6-2 集合的不重復特性應用(案例:提取唯一值記錄)示例代碼詳細解析案例說明6-3 集合成員添加與刪除示例代碼代碼解析直觀示意(Excel 模擬表格)6-4 集合成員添加…

MySQL 約束(入門版)

目錄 一、約束的基本概念 二、約束演示 三、外鍵約束 &#xff08;一&#xff09;介紹 &#xff08;二&#xff09;外鍵約束語法 &#xff08;三&#xff09;刪除/更新行為 一、約束的基本概念 1、概念&#xff1a;約束是作用于表中字段上的規則&#xff0c;用于限制存儲…

【ISP】ISP pipeline(AI)

ISP Pipeline 全流程概覽 ISP&#xff08;Image Signal Processing&#xff0c;圖像信號處理&#xff09;流程通常從原始 Bayer 數據出發&#xff0c;經過一系列模塊處理&#xff0c;逐步完成圖像校正和增強&#xff0c;最終生成用于顯示或編碼的標準圖像。常見處理模塊包括&a…

【Rust開發】Rust快速入門,開發出Rust的第一個Hello World

?? 歡迎大家來到景天科技苑?? &#x1f388;&#x1f388; 養成好習慣&#xff0c;先贊后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者簡介&#xff1a;景天科技苑 &#x1f3c6;《頭銜》&#xff1a;大廠架構師&#xff0c;華為云開發者社區專家博主&#xff0c;…

Google Chrome下載受限制的解決方案【方法指南】

在國內使用網絡時&#xff0c;部分用戶在嘗試訪問Google Chrome官網下載谷歌瀏覽器時&#xff0c;常常遇到網頁無法打開或文件下載失敗的情況。這種下載受限制的問題多由網絡訪問政策或DNS解析異常導致。為了正常獲取Google Chrome的最新版安裝程序&#xff0c;用戶需要通過一些…

使用 new EventSource 實現前端實時通信

示例&#xff1a; eventSource單向通信 1. 什么是 EventSource&#xff1f; EventSource 是瀏覽器提供的一種實現服務器推送&#xff08;Server-Sent Events&#xff0c;簡稱 SSE&#xff09;功能的 API。它是基于 HTTP 協議的單向通信機制&#xff0c;可以通過服務器將實時數…

Android Input——查找并添加目標窗口(七)

在 Android 輸入系統中,InputDispatcher 的核心職責之一是將輸入事件正確地傳遞到目標窗口。上一篇文章我們介紹到 InputDispatcher 事件分發調用到 findFocusedWindowTargetsLocked() 函數查找焦點窗口,并將焦點窗口添加到目標窗口,這里我們繼續往下看。 一、獲取焦點窗口…

Spring Boot中Spring MVC相關配置的詳細描述及表格總結

以下是Spring Boot中Spring MVC相關配置的詳細描述及表格總結&#xff1a; Spring MVC 配置項詳解 1. 異步請求配置 spring.mvc.async.request-timeout 描述&#xff1a;設置異步請求的超時時間&#xff08;單位&#xff1a;毫秒&#xff09;。默認值&#xff1a;未設置&…

HTTP GET 和 POST 請求有什么區別

HTTP 的 GET 和 POST 請求是兩種常見的 HTTP 請求方法&#xff0c;它們有不同的特點和應用場景。以下是它們的主要區別&#xff1a; 1. 用途 GET&#xff1a;用于從服務器獲取數據或資源。GET 請求會附帶查詢參數在 URL 中&#xff0c;通常用于請求數據&#xff0c;如加載網頁…

從入門到精通【MySQL】 聯合查詢

文章目錄 &#x1f4d5;摘要&#x1f4d5;1. 多表聯合查詢時MySQL內部原理??1.1 實例&#xff1a;一個完整的聯合查詢過程 &#x1f4d5;2. 內連接&#x1f4d5;3. 外連接&#x1f4d5;4. 自連接&#x1f4d5;5. 子查詢??5.1 單行子查詢??5.2 多行子查詢??5.3 多列子查…

高可用之戰:Redis Sentinal(哨兵模式)

參考&#xff1a;Redis系列24&#xff1a;Redis使用規范 - Hello-Brand - 博客園 1 背景 在我們的《Redis高可用之戰&#xff1a;主從架構》篇章中&#xff0c;介紹了Redis的主從架構模式&#xff0c;可以有效的提升Redis服務的可用性&#xff0c;減少甚至避免Redis服務發生完…