在Java中如何实现图书借阅历史记录查询

来源:Golang编程网作者:柬埔寨程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《在Java中如何实现图书借阅历史记录查询》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《在Java中如何实现图书借阅历史记录查询》有用,将其分享出去将是对创作者最好的鼓励。

图书借阅历史记录查询是图书管理系统的必备功能,需要结合数据库存储、后端逻辑处理和前端展示三个部分共同实现,下面将从整体架构到具体代码逐步说明实现方法。

一、数据库表设计

首先需要设计存储借阅记录的数据库表,通常借阅记录需要关联图书信息、读者信息,以下是核心表结构示例:

-- 图书表
CREATE TABLE book (
    id INT PRIMARY KEY AUTO_INCREMENT,
    book_name VARCHAR(100) NOT NULL COMMENT '图书名称',
    author VARCHAR(50) COMMENT '作者',
    isbn VARCHAR(30) UNIQUE COMMENT 'ISBN号'
);

-- 读者表
CREATE TABLE reader (
    id INT PRIMARY KEY AUTO_INCREMENT,
    reader_name VARCHAR(50) NOT NULL COMMENT '读者姓名',
    reader_no VARCHAR(30) UNIQUE COMMENT '读者编号'
);

-- 借阅记录表
CREATE TABLE borrow_record (
    id INT PRIMARY KEY AUTO_INCREMENT,
    book_id INT NOT NULL COMMENT '图书ID',
    reader_id INT NOT NULL COMMENT '读者ID',
    borrow_time DATETIME NOT NULL COMMENT '借阅时间',
    return_time DATETIME COMMENT '归还时间',
    status TINYINT NOT NULL DEFAULT 0 COMMENT '状态 0未归还 1已归还',
    FOREIGN KEY (book_id) REFERENCES book(id),
    FOREIGN KEY (reader_id) REFERENCES reader(id)
);

二、后端实体类定义

使用Spring Boot开发时,首先需要定义对应的实体类,这里采用MyBatis-Plus作为持久层框架:

// 借阅记录实体类
package com.example.library.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;

@Data
@TableName("borrow_record")
public class BorrowRecord {
    private Integer id;
    private Integer bookId;
    private Integer readerId;
    private LocalDateTime borrowTime;
    private LocalDateTime returnTime;
    private Integer status;
    // 关联查询的扩展字段,不对应数据库表列
    private String bookName;
    private String readerName;
}

三、借阅记录查询接口开发

查询功能通常需要支持多条件筛选,比如按读者编号、图书名称、借阅时间范围、归还状态等条件查询,同时需要支持分页,以下是Controller和Service层的实现:

1. Controller层代码

package com.example.library.controller;

import com.example.library.common.Result;
import com.example.library.dto.BorrowRecordQueryDTO;
import com.example.library.service.BorrowRecordService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
@RequestMapping("/borrowRecord")
public class BorrowRecordController {

    @Resource
    private BorrowRecordService borrowRecordService;

    @GetMapping("/list")
    public Result queryBorrowRecords(BorrowRecordQueryDTO queryDTO) {
        return Result.success(borrowRecordService.queryBorrowRecords(queryDTO));
    }
}

2. 查询参数DTO定义

package com.example.library.dto;

import lombok.Data;
import java.time.LocalDateTime;

@Data
public class BorrowRecordQueryDTO {
    private String readerNo; // 读者编号
    private String bookName; // 图书名称
    private LocalDateTime startTime; // 借阅开始时间
    private LocalDateTime endTime; // 借阅结束时间
    private Integer status; // 归还状态
    private Integer pageNum = 1; // 页码
    private Integer pageSize = 10; // 每页条数
}

3. Service层实现

Service层需要编写关联查询的逻辑,将借阅记录、图书信息、读者信息关联起来:

package com.example.library.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.library.dto.BorrowRecordQueryDTO;
import com.example.library.entity.BorrowRecord;
import com.example.library.mapper.BorrowRecordMapper;
import com.example.library.service.BorrowRecordService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.List;

@Service
public class BorrowRecordServiceImpl implements BorrowRecordService {

    @Resource
    private BorrowRecordMapper borrowRecordMapper;

    @Override
    public Page<BorrowRecord> queryBorrowRecords(BorrowRecordQueryDTO queryDTO) {
        Page<BorrowRecord> page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize());
        // 这里使用自定义SQL实现关联查询,或者在Mapper中编写关联查询方法
        List<BorrowRecord> records = borrowRecordMapper.queryRecordsByCondition(
            page,
            queryDTO.getReaderNo(),
            queryDTO.getBookName(),
            queryDTO.getStartTime(),
            queryDTO.getEndTime(),
            queryDTO.getStatus()
        );
        page.setRecords(records);
        return page;
    }
}

4. Mapper层自定义SQL

package com.example.library.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.library.entity.BorrowRecord;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.time.LocalDateTime;
import java.util.List;

public interface BorrowRecordMapper extends BaseMapper<BorrowRecord> {

    @Select("""
        SELECT
            br.*,
            b.book_name AS bookName,
            r.reader_name AS readerName
        FROM borrow_record br
        LEFT JOIN book b ON br.book_id = b.id
        LEFT JOIN reader r ON br.reader_id = r.id
        <where>
            <if test="readerNo != null and readerNo != ''">
                AND r.reader_no = #{readerNo}
            </if>
            <if test="bookName != null and bookName != ''">
                AND b.book_name LIKE CONCAT('%', #{bookName}, '%')
            </if>
            <if test="startTime != null">
                AND br.borrow_time >= #{startTime}
            </if>
            <if test="endTime != null">
                AND br.borrow_time <= #{endTime}
            </if>
            <if test="status != null">
                AND br.status = #{status}
            </if>
        </where>
        ORDER BY br.borrow_time DESC
    """)
    List<BorrowRecord> queryRecordsByCondition(
        Page<BorrowRecord> page,
        @Param("readerNo") String readerNo,
        @Param("bookName") String bookName,
        @Param("startTime") LocalDateTime startTime,
        @Param("endTime") LocalDateTime endTime,
        @Param("status") Integer status
    );
}

四、前端查询页面示例

前端可以使用Vue或者普通HTML页面实现查询表单和结果展示,以下是简单的HTML示例:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>借阅记录查询</title>
    <style>
        .search-form { margin: 20px 0; }
        .search-form input, .search-form select { margin-right: 10px; padding: 5px; }
        table { border-collapse: collapse; width: 100%; }
        th, td { border: 1px solid #ccc; padding: 8px; text-align: center; }
    </style>
</head>
<body>
    <div class="search-form">
        <input type="text" id="readerNo" placeholder="读者编号">
        <input type="text" id="bookName" placeholder="图书名称">
        <select id="status">
            <option value="">全部状态</option>
            <option value="0">未归还</option>
            <option value="1">已归还</option>
        </select>
        <button onclick="queryRecords()">查询</button>
    </div>
    <table>
        <thead>
            <tr>
                <th>ID</th>
                <th>图书名称</th>
                <th>读者姓名</th>
                <th>借阅时间</th>
                <th>归还时间</th>
                <th>状态</th>
            </tr>
        </thead>
        <tbody id="recordBody"></tbody>
    </table>
    <div id="pageInfo"></div>

    <script>
        function queryRecords(pageNum = 1) {
            const readerNo = document.getElementById('readerNo').value;
            const bookName = document.getElementById('bookName').value;
            const status = document.getElementById('status').value;
            // 这里使用fetch调用后端接口,实际项目中替换为自己的后端地址
            fetch(`http://ipipp.com:8080/borrowRecord/list?readerNo=${readerNo}&bookName=${bookName}&status=${status}&pageNum=${pageNum}`)
                .then(res => res.json())
                .then(data => {
                    if (data.code === 200) {
                        renderTable(data.data.records);
                        renderPage(data.data.current, data.data.pages);
                    }
                });
        }

        function renderTable(records) {
            const tbody = document.getElementById('recordBody');
            tbody.innerHTML = '';
            records.forEach(record => {
                const tr = document.createElement('tr');
                tr.innerHTML = `
                    <td>${record.id}</td>
                    <td>${record.bookName}</td>
                    <td>${record.readerName}</td>
                    <td>${record.borrowTime}</td>
                    <td>${record.returnTime || '未归还'}</td>
                    <td>${record.status === 0 ? '未归还' : '已归还'}</td>
                `;
                tbody.appendChild(tr);
            });
        }

        function renderPage(current, total) {
            const pageInfo = document.getElementById('pageInfo');
            let pageHtml = '';
            for (let i = 1; i <= total; i++) {
                if (i === current) {
                    pageHtml += `<span style="margin:0 5px;color:red">${i}</span>`;
                } else {
                    pageHtml += `<span style="margin:0 5px;cursor:pointer" onclick="queryRecords(${i})">${i}</span>`;
                }
            }
            pageInfo.innerHTML = pageHtml;
        }

        // 页面加载时查询第一页数据
        window.onload = () => queryRecords();
    </script>
</body>
</html>

五、常见问题说明

  • 如果查询速度较慢,可以给borrow_record表的book_idreader_idborrow_time字段添加索引提升查询效率
  • 时间范围查询需要注意时区问题,建议统一使用UTC时间或者服务器本地时间存储和查询
  • 分页插件的配置需要在Spring Boot配置类中添加MyBatis-Plus的分页拦截器,否则分页不会生效

Java图书借阅系统借阅记录查询MySQLSpring_Boot修改时间:2026-06-16 09:45:59

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。