Java图书管理系统操作步骤

1. 创建目录文件

mkdir -p src/main/java/com/xyxy/feng/controller src/main/java/com/xyxy/feng/entity src/main/java/com/xyxy/feng/mapper src/main/java/com/xyxy/feng/service src/main/resources/static && touch pom.xml src/main/java/com/xyxy/feng/BookManagementApplication.java src/main/java/com/xyxy/feng/controller/BookController.java src/main/java/com/xyxy/feng/entity/Book.java src/main/java/com/xyxy/feng/mapper/BookMapper.java src/main/java/com/xyxy/feng/service/BookService.java src/main/resources/application.properties src/main/resources/static/book.html

2. 数据库操作

create database test;
use test;

# 图书表
create table book(
  id int auto_increment primary key,
  name varchar(32),
  type varchar(32),
  author varchar(32),
  price float,
  pic varchar(128),
  create_date datetime
);

# 插入数据
insert into book values(1,'西游记1','文学','吴承恩',19.9,'xyj.jpg','1999-9-9 1:1:1');
insert into book values(2,'西游记2','文学','吴承恩',19.9,'xyj.jpg','1999-9-9 1:1:1');
insert into book values(3,'西游记3','文学','吴承恩',19.9,'xyj.jpg','1999-9-9 1:1:1');
insert into book values(4,'西游记4','文学','吴承恩',19.9,'xyj.jpg','1999-9-9 1:1:1');
insert into book values(5,'西游记5','文学','吴承恩',19.9,'xyj.jpg','1999-9-9 1:1:1');
insert into book values(6,'西游记6','文学','吴承恩',19.9,'xyj.jpg','1999-9-9 1:1:1');
insert into book values(7,'西游记7','文学','吴承恩',19.9,'xyj.jpg','1999-9-9 1:1:1');
insert into book values(8,'西游记8','文学','吴承恩',19.9,'xyj.jpg','1999-9-9 1:1:1');

3. 编写java代码

3.1 controller

BookController.java 用于处理HTTP请求,实现RESTful API。


package com.xyxy.feng.controller;

import com.xyxy.feng.entity.Book;
import com.xyxy.feng.service.BookService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/book")
public class BookController {

    private static final Logger logger = LoggerFactory.getLogger(BookController.class);

    @Autowired
    private BookService bookService;

    // 获取所有图书
    @GetMapping("/getAllBooks")
    public List<Book> getAllBooks() {
        return bookService.getAllBooks();
    }

    // 获取图书总数
    @GetMapping("/getNums")
    public int getNums() {
        return bookService.getNums();
    }

    // 分页获取图书
    @GetMapping("/getBooksByPage")
    public Map<String, Object> getBooksByPage(@RequestParam("page") int page, @RequestParam("limit") int limit) {
        int start = (page - 1) * limit;
        List<Book> books = bookService.getBooksByPage(start, limit);
        int total = bookService.getNums();
        Map<String, Object> result = new HashMap<>();
        result.put("data", books);
        result.put("total", total);
        return result;
    }

    // 按编号获取图书
    @GetMapping("/getBookById")
    public Book getBookById(@RequestParam("id") int id) {
        return bookService.getBookById(id);
    }

    // 按名字获取图书
    @GetMapping("/getBooksByName")
    public List<Book> getBooksByName(@RequestParam("name") String name) {
        return bookService.getBooksByName(name);
    }

    // 增加图书
    @PostMapping("/addBook")
    public String addBook(@RequestBody Map<String, String> map) throws Exception {
        String name = map.get("name");
        String type = map.get("type");
        String author = map.get("author");
        Float price = Float.valueOf(map.get("price"));
        String pic = map.get("pic");
        String createDateStr = map.get("createDate");

        logger.info("开始添加图书");
        logger.info("name:" + name);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parsedDate = dateFormat.parse(createDateStr);

        Book book = new Book(-1, name, type, author, price, pic, parsedDate);
        bookService.addBook(book);
        return "ok";
    }

    // 删除图书
    @DeleteMapping("/deleteBook")
    public String deleteBook(@RequestParam("id") int id) {
        bookService.deleteBook(id);
        return "ok";
    }

    // 修改图书
    @PutMapping("/updateBook")
    public String updateBook(@RequestBody Map<String, String> map) throws Exception {
        int id = Integer.parseInt(map.get("id"));
        String name = map.get("name");
        String type = map.get("type");
        String author = map.get("author");
        float price = Float.parseFloat(map.get("price"));
        String pic = map.get("pic");
        String createDateStr = map.get("createDate");

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date parsedDate = dateFormat.parse(createDateStr);

        Book book = new Book(id, name, type, author, price, pic, parsedDate);
        bookService.updateBook(book);
        return "ok";
    }
}

3.2 Entity

Book.java 实体类,代表数据库中的图书表。

package com.xyxy.feng.entity;

import java.util.Date;
import java.util.Objects;

//图书类
public class Book implements java.io.Serializable{

    //编号
    public int id;

    //名字
    public  String name;

    //类型
    public String type;

    //作者
    public   String author;

    //价格
    public   float price;

    //图片
    public  String pic;

    //出版日期
    public  Date  createDate;

    public Book() {
    }

    public Book(int id, String name,String type, String author, float price, String pic, Date createDate) {
        this.id = id;
        this.name = name;
        this.type=type;
        this.author = author;
        this.price = price;
        this.pic = pic;
        this.createDate = createDate;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public String getPic() {
        return pic;
    }

    public void setPic(String pic) {
        this.pic = pic;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return id == book.id && Float.compare(price, book.price) == 0 && Objects.equals(name, book.name) && Objects.equals(type, book.type) && Objects.equals(author, book.author) && Objects.equals(pic, book.pic) && Objects.equals(createDate, book.createDate);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, type, author, price, pic, createDate);
    }
}

3.3 Mapper

BookMapper.java 接口,使用MyBatis注解实现SQL映射。


package com.xyxy.feng.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.type.JdbcType;
import java.util.List;
import com.xyxy.feng.entity.Book;

@Mapper      //数据库服务接口
@Repository //是数据库仓库类
public interface BookMapper {

    // 获取所有图书
    @Select("SELECT * FROM book")
    @Results({
            @Result(property = "id", column = "id", jdbcType = JdbcType.INTEGER),
            @Result(property = "name", column = "name", jdbcType = JdbcType.VARCHAR),
            @Result(property = "type", column = "type", jdbcType = JdbcType.VARCHAR),
            @Result(property = "author", column = "author", jdbcType = JdbcType.VARCHAR),
            @Result(property = "price", column = "price", jdbcType = JdbcType.FLOAT),
            @Result(property = "pic", column = "pic", jdbcType = JdbcType.VARCHAR),
            @Result(property = "createDate", column = "create_date", jdbcType = JdbcType.DATE)
    })
    List<Book> getAllBooks();

    //获取图书总数
    @Select("select count(*) from book")
    int getNums();

    // 分页获取所有图书
    @Select("SELECT * FROM book LIMIT #{start}, #{limit}")
    @Results({
            @Result(property = "id", column = "id", jdbcType = JdbcType.INTEGER),
            @Result(property = "name", column = "name", jdbcType = JdbcType.VARCHAR),
            @Result(property = "type", column = "type", jdbcType = JdbcType.VARCHAR),
            @Result(property = "author", column = "author", jdbcType = JdbcType.VARCHAR),
            @Result(property = "price", column = "price", jdbcType = JdbcType.FLOAT),
            @Result(property = "pic", column = "pic", jdbcType = JdbcType.VARCHAR),
            @Result(property = "createDate", column = "create_date", jdbcType = JdbcType.DATE)
    })
    List<Book> getBooksByPage(@Param("start") int start, @Param("limit") int limit);

    // 按编号获取图书
    @Select("SELECT * FROM book WHERE id = #{id}")
    Book getBookById(@Param("id") int id);

    // 按名字获取图书
    @Select("SELECT * FROM book WHERE name LIKE CONCAT('%', #{name}, '%')")
    List<Book> getBooksByName(@Param("name") String name);

    // 增加图书
    @Insert("INSERT INTO book (name, type, author, price, pic, create_date) VALUES(#{name}, #{type}, #{author}, #{price}, #{pic}, #{createDate})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    void addBook(Book book);

    // 删除图书
    @Delete("DELETE FROM book WHERE id = #{id}")
    void deleteBook(@Param("id") int id);

    // 修改图书
    @Update("UPDATE book SET name = #{name}, type = #{type}, author = #{author}, price = #{price}, pic = #{pic}, create_date = #{createDate} WHERE id = #{id}")
    void updateBook(Book book);
}

3.4 Service

BookService.java 服务类,实现业务逻辑。


package com.xyxy.feng.service;

import com.xyxy.feng.entity.Book;
import com.xyxy.feng.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

//图书服务类
@Service
public class BookService {

    @Autowired
    BookMapper bookMapper;

    public List<Book> getAllBooks() {
        return bookMapper.getAllBooks();
    }

    public int getNums() {
        return bookMapper.getNums();
    }

    public List<Book> getBooksByPage(int start, int limit) {
        return bookMapper.getBooksByPage(start, limit);
    }

    public Book getBookById(int id) {
        return bookMapper.getBookById(id);
    }

    public List<Book> getBooksByName(String name) {
        return bookMapper.getBooksByName(name);
    }

    public void addBook(Book book) {
        bookMapper.addBook(book);
    }

    public void deleteBook(int id) {
        bookMapper.deleteBook(id);
    }

    public void updateBook(Book book) {
        bookMapper.updateBook(book);
    }
}

3.5 Application

BookManagementApplication.java 应用程序入口。

package com.xyxy.feng;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class BookManagementApplication {
    public static void main(String[] args) {
        SpringApplication.run(BookManagementApplication.class, args);
    }
}

4. 编写resources代码

4.1 编写前端代码

book.html 前端页面,使用Vue.js实现数据绑定和交互。

<!DOCTYPE html>
<html lang="cn" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
  <meta charset="UTF-8">
  <title>图书管理系统</title>
  <!-- You might need to download these files or use CDNs -->
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <style>
      body {
          font-family: sans-serif;
          padding: 20px;
      }
      table {
          border-collapse: collapse;
          width: 100%;
          margin-top: 15px;
          margin-bottom: 15px;
      }
      th, td {
          border: 1px solid #ddd;
          padding: 8px;
          text-align: left;
      }
      th {
          background-color: #f2f2f2;
      }
      button {
          padding: 5px 10px;
          margin-right: 5px;
          cursor: pointer;
      }
      input[type=text] {
          padding: 6px;
          margin-right: 5px;
          margin-bottom: 10px;
      }
      .pagination button {
           margin-top: 10px;
      }
      .add-book-form {
          margin-top: 20px;
          padding: 15px;
          border: 1px solid #ccc;
          border-radius: 5px;
      }
      .add-book-form label {
          display: block;
          margin-bottom: 5px;
      }
      .add-book-form input[type=text] {
          width: calc(100% - 16px); /* Adjust for padding */
          margin-bottom: 10px;
      }
  </style>
</head>
<body>
<div id="app">
  <h2>图书管理系统</h2>

  <div>
      书名:<input id="bookName" type="text" v-model="searchName">
      <button v-on:click="getBooksByName">查找</button>
  </div>

  <table>
      <thead>
          <tr>
              <th>ID</th>
              <th>书名</th>
              <th>类型</th>
              <th>作者</th>
              <th>价格</th>
              <th>图片</th>
              <th>出版日期</th>
              <th>操作</th>
          </tr>
      </thead>
      <tbody>
          <tr v-for="book in bookList">
              <td v-text="book.id"></td>
              <td v-text="book.name"></td>
              <td v-text="book.type"></td>
              <td v-text="book.author"></td>
              <td v-text="book.price"></td>
              <td v-text="book.pic"></td>
              <td v-text="formatDate(book.createDate)"></td>
              <td>
                  <button v-on:click="prepareUpdate(book)">修改</button>
                  <button v-on:click="deleteBook(book.id)">删除</button>
              </td>
          </tr>
      </tbody>
  </table>

  <div class="pagination">
      <button v-on:click="firstPage" :disabled="page <= 1">首页</button>
      <button v-on:click="prePage" :disabled="page <= 1">上一页</button>
      <span>第 {{ page }} 页 / 共 {{ totalPages }} 页</span>
      <button v-on:click="nextPage" :disabled="page >= totalPages">下一页</button>
      <button v-on:click="lastPage" :disabled="page >= totalPages">末页</button>
  </div>

  <div class="add-book-form">
      <h3>{{ isUpdating ? '修改图书' : '增加图书' }}</h3>
      <input type="hidden" v-model="currentBook.id">
      <label>名字:</label><input type="text" v-model="currentBook.name"/><br/>
      <label>类型:</label><input type="text" v-model="currentBook.type"/><br/>
      <label>作者:</label><input type="text" v-model="currentBook.author"/><br/>
      <label>价格:</label><input type="text" v-model="currentBook.price"/><br/>
      <label>图片:</label><input type="text" v-model="currentBook.pic"/><br/>
      <label>日期:</label><input type="text" v-model="currentBook.createDate" placeholder="YYYY-MM-DD"/><br/>
      <button v-if="isUpdating" v-on:click="updateBook">确认修改</button>
      <button v-else v-on:click="addBook">增加</button>
      <button v-if="isUpdating" v-on:click="cancelUpdate">取消</button>
  </div>
</div>

<script>
  const { createApp, ref, reactive, onMounted, computed } = Vue;

  const app = createApp({
      setup() {
          const bookList = ref([]);
          const page = ref(1);
          const size = ref(5);
          const total = ref(0);
          const searchName = ref('');
          const isUpdating = ref(false);
          const currentBook = reactive({
              id: null,
              name: '',
              type: '',
              author: '',
              price: '',
              pic: '',
              createDate: ''
          });

          const totalPages = computed(() => Math.ceil(total.value / size.value));

          const formatDate = (dateString) => {
              if (!dateString) return '';
              
              // 尝试解析ISO格式
              let date = new Date(dateString);
              if (!isNaN(date.getTime())) {
                  return date.toISOString().split('T')[0];
              }
              
              // 尝试解析其他常见格式
              const match = dateString.match(/(\d{4})[\/-](\d{1,2})[\/-](\d{1,2})/);
              if (match) {
                  return `{match[1]}-{match[2].padStart(2, '0')}-${match[3].padStart(2, '0')}`;
              };
              
              return dateString;
          };

          const getBooksByPage = async () => {
              try {
                  console.log(`分页获取数据: page=${page.value}, limit=${size.value}`);
                  const response = await axios.get('/book/getBooksByPage', {
                      params: {
                          page: page.value,
                          limit: size.value
                      }
                  });
                  bookList.value = response.data.data;
                  total.value = response.data.total;
                  console.log('数据加载:', bookList.value);
              } catch (error) {
                  console.error("获取图书列表失败:", error);
                  alert('获取图书列表失败!');
              }
          };

          const deleteBook = async (id) => {
              if (!confirm(`确定要删除 ID 为 ${id} 的图书吗?`)) return;
              try {
                  const response = await axios.delete('/book/deleteBook', { params: { id: id } });
                  if (response.data === 'ok') {
                      alert('删除成功!');
                      // If the last item on the current page is deleted, go to the previous page
                      if (bookList.value.length === 1 && page.value > 1) {
                          page.value--;
                      }
                      getBooksByPage();
                  } else {
                      alert('删除失败: ' + response.data);
                  }
              } catch (error) {
                  console.error("删除图书失败:", error);
                  alert('删除图书失败!');
              }
          };

          const addBook = async () => {
              if (!currentBook.name || !currentBook.author || !currentBook.type || !currentBook.price || !currentBook.createDate) {
                  alert('请填写所有必填项!');
                  return;
              }
               if (!/^d{4}-d{2}-d{2}$/.test(currentBook.createDate)) {
                  alert('日期格式必须为 YYYY-MM-DD');
                  return;
              }
              try {
                  const bookData = { ...currentBook }; // Create a copy
                  delete bookData.id; // Remove id for add operation
                  const response = await axios.post('/book/addBook', bookData);
                  if (response.data === 'ok') {
                      alert('增加成功!');
                      resetForm();
                      lastPage(); // Go to the last page to see the new book
                  } else {
                      alert('增加失败: ' + response.data);
                  }
              } catch (error) {
                  console.error("增加图书失败:", error);
                  alert('增加图书失败!');
              }
          };

          const getBooksByName = async () => {
              try {
                  const response = await axios.get('/book/getBooksByName', { params: { name: searchName.value } });
                  bookList.value = response.data;
                  // Note: Searching might reset pagination logic depending on requirements
                  // For simplicity, we just display the results here.
                  // You might want to disable pagination or adjust total pages.
                  total.value = bookList.value.length; // Simple update for total
                  page.value = 1; // Reset to first page for search results
              } catch (error) {
                  console.error("按名称搜索图书失败:", error);
                  alert('按名称搜索图书失败!');
              }
          };

          const prepareUpdate = (book) => {
              isUpdating.value = true;
              currentBook.id = book.id;
              currentBook.name = book.name;
              currentBook.type = book.type;
              currentBook.author = book.author;
              currentBook.price = book.price;
              currentBook.pic = book.pic;
              currentBook.createDate = formatDate(book.createDate); // Format date for input field
          };

          const updateBook = async () => {
               if (!currentBook.name || !currentBook.author || !currentBook.type || !currentBook.price || !currentBook.createDate) {
                  alert('请填写所有必填项!');
                  return;
              }
              if (!/^\d{4}-\d{2}-\d{2}$/.test(currentBook.createDate)) {
                  alert('日期格式必须为 YYYY-MM-DD');
                  return;
              }
              try {
                  const response = await axios.put('/book/updateBook', currentBook);
                  if (response.data === 'ok') {
                      alert('修改成功!');
                      resetForm();
                      getBooksByPage(); // Refresh current page
                  } else {
                      alert('修改失败: ' + response.data);
                  }
              } catch (error) {
                  console.error("修改图书失败:", error);
                  alert('修改图书失败!');
              }
          };

          const cancelUpdate = () => {
              resetForm();
          };

          const resetForm = () => {
              isUpdating.value = false;
              currentBook.id = null;
              currentBook.name = '';
              currentBook.type = '';
              currentBook.author = '';
              currentBook.price = '';
              currentBook.pic = '';
              currentBook.createDate = '';
          };

          const firstPage = () => {
              if (page.value > 1) {
                  page.value = 1;
                  getBooksByPage();
              }
          };

          const prePage = () => {
              if (page.value > 1) {
                  page.value--;
                  getBooksByPage();
              }
          };

          const nextPage = () => {
              if (page.value < totalPages.value) {
                  page.value++;
                  getBooksByPage();
              }
          };

          const lastPage = () => {
               const lastPg = totalPages.value;
              if (page.value < lastPg) {
                  page.value = lastPg;
                  getBooksByPage();
              }
          };

          onMounted(() => {
              console.log("Vue 实例已挂载");
              getBooksByPage();
          });

          return {
              bookList,
              page,
              size,
              total,
              totalPages,
              searchName,
              isUpdating,
              currentBook,
              formatDate,
              getBooksByPage,
              deleteBook,
              addBook,
              getBooksByName,
              prepareUpdate,
              updateBook,
              cancelUpdate,
              firstPage,
              prePage,
              nextPage,
              lastPage
          };
      }
  });

  app.mount("#app");
</script>
</body>
</html>

4.2 编写数据库代码

application.properties 配置文件,设置数据库连接等参数。

spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=你的数据库密码
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.thymeleaf.cache=false
server.port=8080

5. 编译并运行

编写pem.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.7.18</version> <!-- Or a later compatible version -->
      <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>com.xyxy.feng</groupId>
  <artifactId>book-management</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>book-management</name>
  <description>Book Management System</description>
  <properties>
      <java.version>11</java.version> <!-- Or your Java version -->
  </properties>
  <dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
          <groupId>org.mybatis.spring.boot</groupId>
          <artifactId>mybatis-spring-boot-starter</artifactId>
          <version>2.2.2</version> <!-- Or a later compatible version -->
      </dependency>

      <dependency>
          <groupId>com.mysql</groupId>
          <artifactId>mysql-connector-j</artifactId>
          <scope>runtime</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
      </dependency>
  </dependencies>

  <build>
      <plugins>
          <plugin>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-maven-plugin</artifactId>
              <configuration>
                  <mainClass>com.xyxy.feng.BookManagementApplication</mainClass>
              </configuration>
          </plugin>
      </plugins>
  </build>

</project>
mvn spring-boot:run

打开浏览器访问 http://localhost:8080/book.html 可以看到图书管理系统的界面。