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 可以看到图书管理系统的界面。