当前位置:   article > 正文

【图书管理系统】使用Springboot +JPA+thymeleaf+MySQL制作一个图书管理系统_springboot+mybatis+thymeleaf(idea)图书管理系统

springboot+mybatis+thymeleaf(idea)图书管理系统


项目介绍

  该项目是一个基于Spring Boot、JPA、Thymeleaf和MySQL的数据驱动的图书管理系统。它提供了对图书的增加、删除、更新、查询和分页等功能,并支持自定义查询和排序。

  通过该图书管理系统,用户可以方便地进行图书的管理和查询,提高图书馆的工作效率和服务质量。同时,用户界面友好,操作简单,适合不同用户使用。

在这里插入图片描述


一、新建项目

  在使用IDEA创建项目时,建议选择Spring Initializr,并选择Maven作为构建工具。为了满足项目需求,推荐使用JDK 17作为项目的Java开发环境。在依赖管理中,需要添加以下五个依赖:Lombok、Spring Web、Thymeleaf、Spring Data JPA和MySQL Driver。这些依赖将为项目提供必要的功能和库,包括简化Java开发、实现Web应用、使用模板引擎、实现数据持久化以及与MySQL数据库进行交互。选择这些依赖将为项目提供稳定、高效的开发基础,使开发过程更加顺利和便捷
在这里插入图片描述
在这里插入图片描述


二、系统设计步骤

1.连接数据库

源代码:

# 数据源URL,用于连接MySQL数据库
spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8

# 数据库用户名
spring.datasource.username=root

# 数据库密码
spring.datasource.password=123456

# 数据库驱动类名
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Hibernate方言,用于指定MySQL方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

# Hibernate的ddl-auto属性(create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto=update

# Hibernate SQL日志级别设置为DEBUG
logging.level.org.hibernate.SQL=DEBUG

# Hibernate类型日志级别设置为TRACE
logging.level.org.hibernate.type=TRACE



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在这里插入图片描述

  这个程序是一个Spring Boot应用程序的配置文件,用于配置应用程序与MySQL数据库之间的连接和数据访问。

2.model层

源代码:

package com.example.book.model;

import jakarta.persistence.*;
import lombok.Data;

@Data
@Entity
@Table(name = "Book")

public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(name = "书名")
    private String name;

    @Column(name = "价格")
    private String Price;

    @Column(name = "作者")
    private String author;

    @Column(name = "索书号")
    private String ISBN;

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

  通过定义了一个名为Book的Java实体类,用于映射数据库中的"Book"表,每个字段(id、name、Price、author和ISBN)都与表中的相应列进行映射,并通过JPA注解和Lombok简化了实体类的编写和数据库交互过程。

3.Service层

  Service层是软件开发中的一种常见架构模式,它在应用程序中扮演着重要的角色。Service层通常用于实现业务逻辑和处理业务规则,作为控制层(Controller)和数据访问层(Repository)之间的中间层。

源代码:

package com.example.book.service;

import com.example.book.model.Book;
import org.springframework.data.domain.Page;

import java.util.List;

public interface BookService {
// 获取所有书籍
List<Book> getAllBooks();

// 保存书籍信息
void saveBook(Book book);

// 根据ID获取书籍
Book getBookById(long id);

// 根据ID删除书籍
void deleteBookById(long id);

// 分页查询书籍
Page<Book> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

  定义一个对书籍数据进行基本的 CRUD(创建、读取、更新、删除)操作的方法,用来访问和管理书籍数据。实际的实现类可以根据需要定义,并使用该接口来访问和操作书籍数据。

4.EmployeeServiceImpl

package com.example.book.service;

import com.example.book.model.Book;
import com.example.book.repository.BookRepository;
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.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class BookServiceImpl implements BookService {

    @Autowired
    private BookRepository bookRepository;

    @Override
    public List<Book> getAllBooks() {
        return bookRepository.findAll();
    }

    @Override
    public void saveBook(Book book) {
        this.bookRepository.save(book);
    }

    @Override
    public Book getBookById(long id) {
        Optional<Book> optional = bookRepository.findById(id);

        Book book = null;

        if (optional.isPresent()) {
            book = optional.get();
        } else {
            System.out.println("Sorry, the book with the specified ID does not exist!");
        }

        return book;
    }

    @Override
    public void deleteBookById(long id) {
        this.bookRepository.deleteById(id);
    }

    @Override
    public Page<Book> findPaginated(int pageNo, int pageSize, String sortField, String sortDirection) {
        Sort sort = sortDirection.equalsIgnoreCase(Sort.Direction.ASC.name())
                ? Sort.by(sortField).ascending()
                : Sort.by(sortField).descending();

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, sort);

        return this.bookRepository.findAll(pageable);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

  实现一个Spring服务类,名为BookServiceImpl。提供了对图书信息的增删改查功能,并支持分页查询。通过依赖注入BookRepository接口的实现,可以访问数据库中的图书数据。其中的方法包括获取所有图书信息的列表、保存和更新图书信息、根据ID查找图书、根据ID删除图书以及实现分页查询功能。Spring服务类实现了如何使用Spring框架和Spring Data JPA来简化对数据库的操作,提供了基本的图书信息管理功能。

5. Controller层

@Controller
public class BookController {

    @Autowired
    private BookService bookService;

    @GetMapping("/")
    public String viewHomePage(Model model) {
        return findPaginated(1, "id", "asc", model);
    }

    @GetMapping("/showNewBookForm")
    public String showNewBookForm(Model model) {
        Book book = new Book();
        model.addAttribute("book", book);
        return "new_book";
    }

    @PostMapping("/saveBook")
    public String saveBook(@ModelAttribute("book") Book book) {
        bookService.saveBook(book);
        return "redirect:/";
    }

    @GetMapping("/showFormForUpdate/{id}")
    public String showFormForUpdate(@PathVariable(value = "id") long id, Model model) {
        Book book = bookService.getBookById(id);
        model.addAttribute("book", book);
        return "update_book";
    }

    @GetMapping("/deleteBook/{id}")
    public String deleteBook(@PathVariable(value = "id") long id) {
        bookService.deleteBookById(id);
        return "redirect:/";
    }

    @RequestMapping(value = "/index1")
    public String index(Model model) {
        Book book = new Book();
        model.addAttribute("book", book);
        return "seek";
    }

    @PostMapping(value = "/show")
    public String show(@ModelAttribute Book book, Model model) {
        Long id = book.getId();
        Book b = bookService.getBookById(id);
        model.addAttribute("book", b);
        return "show";
    }

    @GetMapping("/page/{pageNo}")
    public String findPaginated(@PathVariable(value = "pageNo") int pageNo,
                                @RequestParam("sortField") String sortField,
                                @RequestParam("sortDir") String sortDir,
                                Model model) {
        int pageSize = 5;

        Page<Book> page = bookService.findPaginated(pageNo, pageSize, sortField, sortDir);
        List<Book> listBooks = page.getContent();

        model.addAttribute("currentPage", pageNo);
        model.addAttribute("totalPages", page.getTotalPages());
        model.addAttribute("totalItems", page.getTotalElements());

        model.addAttribute("sortField", sortField);
        model.addAttribute("sortDir", sortDir);
        model.addAttribute("reverseSortDir", sortDir.equals("asc") ? "desc" : "asc");

        model.addAttribute("listBooks", listBooks);
        return "index";
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

  实现一个Spring控制器类,名为BookController。它处理与图书信息相关的HTTP请求,并将其委托给BookService进行相应的业务逻辑操作。
  代码中的主要部分包括处理根路径的GET请求,显示新图书表单的GET请求,保存图书信息的POST请求,显示更新图书表单的GET请求,删除图书的GET请求,以及分页查询图书信息的GET请求。
  控制器类通过依赖注入BookService接口的实现类,即bookService字段,来访问数据库中的图书数据。在各个方法中,它通过调用bookService提供的方法来执行相应的图书信息管理功能,例如获取图书列表、保存图书、根据ID获取图书、删除图书等。然后,根据业务逻辑的结果,将模型数据添加到视图中,并返回相应的视图名称进行展示或重定向。
  Spring控制器类展示了如何使用Spring框架和Spring MVC来处理Web请求,并实现了基本的图书信息管理功能,包括添加、更新、删除和分页查询图书信息。


三、页面情况

1.图书馆管理系统首页


在这里插入图片描述

2.首页页面代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>图书管理系统</title>

    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
    <style>
        body {
            background-color: #87CEFA; /* 设置背景颜色为灰色 */
        }
    </style>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
        }

        .container {
            text-align: center;
        }
    </style>

</head>
<body>

<div class="container my-2">
    <h1>图书管理系统</h1>
    <style>
        h1 {
            font-size: 36px;
            font-weight: bold;
            color: #000000;
            margin-bottom: 20px;
        }
    </style>
    <a th:href = "@{/showNewEmployeeForm}" class="btn btn-primary btn-sm mb-3"> 新增数据 </a>
    <a th:href = "@{/index1}" class="btn btn-primary btn-sm mb-3">查找数据</a>
    <form th:action="@{/search}" method="get" class="d-flex">
        <div class="flex-grow-1">
            <input type="text" name="keyword" placeholder="输入书名进行搜索" class="form-control" />
        </div>
        <button type="submit" class="btn btn-primary ml-2">搜索</button>
    </form>
    <table border="1" class = "table table-striped table-responsive-md">
        <thead>
        <tr>
            <th>
                <a th:href="@{'/page/' + ${currentPage} + '?sortField=email&sortDir=' + ${reverseSortDir}}">
                    ID</a>
            </th>
            <th>
                <a th:href="@{'/page/' + ${currentPage} + '?sortField=firstName&sortDir=' + ${reverseSortDir}}">
                    书名</a>
            </th>
            <th>
                <a th:href="@{'/page/' + ${currentPage} + '?sortField=lastName&sortDir=' + ${reverseSortDir}}">
                    价格</a>
            </th>
            <th>
                <a th:href="@{'/page/' + ${currentPage} + '?sortField=email&sortDir=' + ${reverseSortDir}}">
                    作者</a>
            </th>
            <th>
                <a th:href="@{'/page/' + ${currentPage} + '?sortField=email&sortDir=' + ${reverseSortDir}}">
                    索书号</a>
            </th>

            <th>
                <a th:href="@{'/page/' + ${currentPage} + '?sortField=email&sortDir=' + ${reverseSortDir}}">
                    更新与删除</a>
            </th>
        </tr>
        </thead>
        <tbody>
        <tr th:each="employee : ${listEmployees}">
            <td th:text="${employee.id}"></td>
            <td th:text="${employee.firstName}"></td>
            <td th:text="${employee.lastName}"></td>
            <td th:text="${employee.email}"></td>
            <td th:text="${employee.department}"></td>
            <td> <a th:href="@{/showFormForUpdate/{id}(id=${employee.id})}" class="btn btn-primary">更新</a>
                <a th:href="@{/deleteEmployee/{id}(id=${employee.id})}" class="btn btn-danger">删除</a>
            </td>
        </tr>
        </tbody>
    </table>

    <div th:if = "${totalPages > 1}">
        <div class = "row col-sm-10">
            <div class = "col-sm-3">
                共计[[${totalItems}]]条记录
            </div>
            <div class = "col-sm-5">
					<span th:each="i: ${#numbers.sequence(1, totalPages)}">
						<a th:if="${currentPage != i}" th:href="@{'/page/' + ${i}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">[[${i}]]</a>
						<span th:unless="${currentPage != i}">[[${i}]]</span>  &nbsp; &nbsp;
					</span>
            </div>
            <div class = "col-sm-1">
                <a th:if="${currentPage < totalPages}" th:href="@{'/page/' + ${currentPage + 1}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">Next</a>
                <span th:unless="${currentPage < totalPages}">Next</span>
            </div>

            <div class="col-sm-1">
                <a th:if="${currentPage < totalPages}" th:href="@{'/page/' + ${totalPages}+ '?sortField=' + ${sortField} + '&sortDir=' + ${sortDir}}">Last</a>
                <span th:unless="${currentPage < totalPages}">Last</span>
            </div>
        </div>
    </div>
</div>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116

3.信息添加页


在这里插入图片描述

4.添加页代码

<div class="container">
    <h1>图书管理系统</h1>
    <!-- 标题和页面内容 -->

    <h2>新建图书</h2>
    <!-- 新建图书的标题 -->

    <form action="#" th:action="@{/saveEmployee}" th:object="${employee}" method="POST">
        <!-- 表单开始,action属性指定表单提交的URL路径,th:action用于在服务器端处理表单提交的请求 -->

        <input type="hidden" th:field="*{id}" />
        <!-- 隐藏的输入字段,用于传递图书ID,th:field用于绑定表单字段与模型属性 -->

        <input type="text" th:field="*{firstName}" placeholder="书名" class="form-control mb-4 col-4">
        <!-- 文本输入字段,th:field用于绑定表单字段与模型属性,placeholder属性为字段提供提示信息,class属性为样式设置 -->

        <input type="text" th:field="*{lastName}" placeholder="价格" class="form-control mb-4 col-4">

        <input type="text" th:field="*{email}" placeholder="作者" class="form-control mb-4 col-4">

        <input type="text" th:field="*{department}" placeholder="索书号" class="form-control mb-4 col-4">

        <button type="submit" class="btn btn-info col-2"> 新建图书</button>
        <!-- 提交按钮,点击后提交表单数据 -->

    </form>

    <hr>

    <a th:href="@{/}">返回</a>
    <!-- 返回链接,点击后返回上一页 -->

</div>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

5.信息查询页


在这里插入图片描述

6.查询页代码

<!DOCTYPE html>
<!-- thymeleaf -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>index.html</title>
</head>
<body>
<h1>欢迎访问图书管理系统</h1>
<!-- 因为th:object这里指明接受后台的一个user对象,所以index控制器那里要为model属性添加一个User对象 -->
<form th:action="@{/show}" th:object="${employee}" method="post">
    书名ID:<input type="text" th:field="*{id}" /><br/>
    <input type="submit" value="查询" />
</form>
</body>
</html>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

7.信息更新页


在这里插入图片描述

8.信息更新页代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Employee Management System</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

</head>

<body>
<div class="container">
    <h1>图书信息更新</h1>
    <hr>
    <h2>信息更新</h2>

    <form action="#" th:action="@{/saveEmployee}" th:object="${employee}" method="POST">

        <!-- Add hidden form field to handle update -->
        <input type="hidden" th:field="*{id}" />

        <input type="text" th:field="*{firstName}" class="form-control mb-4 col-4">

        <input type="text" th:field="*{lastName}" class="form-control mb-4 col-4">

        <input type="text" th:field="*{email}" class="form-control mb-4 col-4">
        <input type="text" th:field="*{department}" class="form-control mb-4 col-4">

        <button type="submit" class="btn btn-info col-2"> 信息更新页</button>
    </form>

    <hr>

    <a th:href="@{/}"> Back to Employee List</a>
</div>
</body>

</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

总结

  
  在本次期末实践项目中,我设计并完成了一个图书管理系统。项目采用了Spring Boot作为开发框架,使用JPA与MySQL数据库进行数据持久化,使用Thymeleaf作为模板引擎进行前端页面的渲染。系统主要功能包括图书的增删改查和分页功能,并实现了排序功能。图书的属性包括书名、价格、作者和索书号等。通过自定义查询依据,用户可以查找图书并展示查询结果。

  在项目中,我使用了Spring Boot提供的自动配置功能,简化了项目的搭建和配置过程。通过JPA与MySQL数据库进行交互,实现了图书数据的持久化和管理。使用Thymeleaf模板引擎,我能够轻松地构建并渲染图书管理系统的前端页面。项目的核心逻辑在控制器层和服务层实现,控制器负责接收用户的HTTP请求并调用相应的服务方法进行处理,服务层负责处理具体的业务逻辑。通过使用分页功能,用户可以方便地浏览大量的图书数据。

  总的来说,通过完成图书管理系统的开发,我加深了对Spring Boot、JPA和Thymeleaf的理解和应用,并掌握了数据驱动的系统设计和开发方法。我通过这个项目锻炼了自己的编码能力和问题解决能力,提升了对软件开发全过程的掌控能力。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/58218
推荐阅读
相关标签
  

闽ICP备14008679号