我们将开发一个控制台应用程序,它能够对图书信息进行增、删、改、查等基本操作。

核心功能
- 添加图书: 录入新图书的信息(如ID、书名、作者、价格、库存)。
- 删除图书: 根据图书ID删除指定图书。
- 修改图书: 根据图书ID修改图书信息(如价格、库存)。
- 查询图书:
- 查询所有图书信息。
- 根据ID精确查询一本图书。
- 根据书名模糊查询图书。
- 退出系统: 安全退出程序。
技术栈
- 语言: Java
- 架构模式: MVC
- 数据库: MySQL
- 数据库连接: JDBC (Java Database Connectivity)
- 项目构建: Maven (用于管理依赖和项目结构)
第一步:环境准备
- 安装 JDK: 确保你的电脑上安装了 JDK 8 或更高版本。
- 安装 MySQL: 安装并启动 MySQL 数据库服务。
- 安装 IDE: 推荐使用 IntelliJ IDEA 或 Eclipse。
- 安装 Maven: 用于项目管理和依赖管理。
第二步:创建数据库和表
在 MySQL 中,执行以下 SQL 语句来创建一个名为 library 的数据库,并在其中创建一个 books 表。
-- 创建数据库
CREATE DATABASE IF NOT EXISTS library CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 使用数据库
USE library;
-- 创建图书表
CREATE TABLE IF NOT EXISTS books (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '图书ID',VARCHAR(100) NOT NULL COMMENT '书名',
author VARCHAR(100) NOT NULL COMMENT '作者',
price DECIMAL(10, 2) NOT NULL COMMENT '价格',
stock INT NOT NULL DEFAULT 0 COMMENT '库存'
) COMMENT='图书信息表';
-- 插入一些初始数据用于测试
INSERT INTO books (title, author, price, stock) VALUES
('Java核心技术 卷I 基础知识', 'Cay S. Horstmann', 118.00, 50),
('深入理解Java虚拟机', '周志明', 119.00, 30),
('Effective Java', 'Joshua Bloch', 108.00, 25),
('算法导论', 'Thomas H. Cormen', 128.00, 20);
第三步:创建 Maven 项目并配置
- 在你的 IDE 中创建一个 Maven 项目。
- 打开
pom.xml文件,添加 MySQL 驱动的依赖。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>java-library-management</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version> <!-- 使用你安装的MySQL版本对应的驱动版本 -->
</dependency>
</dependencies>
</project>
第四步:项目结构 (MVC)
我们将按照 MVC 模式组织代码:
src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── library
│ │ ├── controller // 控制层 (C)
│ │ │ └── BookController.java
│ │ ├── model // 模型层 (M)
│ │ │ ├── Book.java
│ │ │ └── BookDao.java (Data Access Object)
│ │ ├── util // 工具类
│ │ │ └── DBUtil.java
│ │ └── Main.java // 程序入口
│ └── resources
└── test
第五步:编写代码
Model (模型层)
Book.java (实体类)
这个类是图书信息的载体,与数据库表 books 结构一一对应。
package com.example.library.model;
public class Book {
private int id;
private String title;
private String author;
private double price;
private int stock;
// 构造方法、Getter 和 Setter
public Book() {}
public Book(String title, String author, double price, int stock) {
this.title = title;
this.author = author;
this.price = price;
this.stock = stock;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getStock() {
return stock;
}
public void setStock(int stock) {
this.stock = stock;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", title='" + title + '\'' +
", author='" + author + '\'' +
", price=" + price +
", stock=" + stock +
'}';
}
}
BookDao.java (数据访问对象)
这个类负责所有与数据库 books 表的交互操作,如增、删、改、查。

package com.example.library.model;
import com.example.library.util.DBUtil;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class BookDao {
// 添加图书
public boolean addBook(Book book) {
String sql = "INSERT INTO books (title, author, price, stock) VALUES (?, ?, ?, ?)";
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, book.getTitle());
pstmt.setString(2, book.getAuthor());
pstmt.setDouble(3, book.getPrice());
pstmt.setInt(4, book.getStock());
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 删除图书 (根据ID)
public boolean deleteBook(int id) {
String sql = "DELETE FROM books WHERE id = ?";
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, id);
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 更新图书
public boolean updateBook(Book book) {
String sql = "UPDATE books SET title = ?, author = ?, price = ?, stock = ? WHERE id = ?";
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, book.getTitle());
pstmt.setString(2, book.getAuthor());
pstmt.setDouble(3, book.getPrice());
pstmt.setInt(4, book.getStock());
pstmt.setInt(5, book.getId());
return pstmt.executeUpdate() > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
// 查询所有图书
public List<Book> getAllBooks() {
List<Book> books = new ArrayList<>();
String sql = "SELECT * FROM books";
try (Connection conn = DBUtil.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
Book book = new Book();
book.setId(rs.getInt("id"));
book.setTitle(rs.getString("title"));
book.setAuthor(rs.getString("author"));
book.setPrice(rs.getDouble("price"));
book.setStock(rs.getInt("stock"));
books.add(book);
}
} catch (SQLException e) {
e.printStackTrace();
}
return books;
}
// 根据ID查询图书
public Book getBookById(int id) {
String sql = "SELECT * FROM books WHERE id = ?";
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, id);
ResultSet rs = pstmt.executeQuery();
if (rs.next()) {
Book book = new Book();
book.setId(rs.getInt("id"));
book.setTitle(rs.getString("title"));
book.setAuthor(rs.getString("author"));
book.setPrice(rs.getDouble("price"));
book.setStock(rs.getInt("stock"));
return book;
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
// 根据书名模糊查询
public List<Book> findBooksByTitle(String titleKeyword) {
List<Book> books = new ArrayList<>();
String sql = "SELECT * FROM books WHERE title LIKE ?";
try (Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "%" + titleKeyword + "%"); // 添加模糊查询的通配符
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
Book book = new Book();
book.setId(rs.getInt("id"));
book.setTitle(rs.getString("title"));
book.setAuthor(rs.getString("author"));
book.setPrice(rs.getDouble("price"));
book.setStock(rs.getInt("stock"));
books.add(book);
}
} catch (SQLException e) {
e.printStackTrace();
}
return books;
}
}
DBUtil.java (数据库工具类)
用于管理数据库连接,避免代码重复。
package com.example.library.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBUtil {
// 数据库连接信息 (请根据你的实际情况修改)
private static final String URL = "jdbc:mysql://localhost:3306/library?useSSL=false&serverTimezone=UTC";
private static final String USER = "root"; // 你的数据库用户名
private static final String PASSWORD = "your_password"; // 你的数据库密码
static {
try {
// 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
System.err.println("MySQL JDBC Driver not found!");
}
}
// 获取数据库连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(URL, USER, PASSWORD);
}
// 关闭资源 (通常在 try-with-resources 中自动关闭,但提供静态方法更规范)
public static void close(Connection conn, Statement stmt, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Controller (控制层)
BookController.java
这个类是 Model 和 View 之间的桥梁,它接收用户的输入,调用 BookDao 的方法进行业务处理,并返回结果。
package com.example.library.controller;
import com.example.library.model.Book;
import com.example.library.model.BookDao;
import java.util.List;
import java.util.Scanner;
public class BookController {
private BookDao bookDao = new BookDao();
private Scanner scanner = new Scanner(System.in);
// 显示主菜单
public void showMenu() {
while (true) {
System.out.println("\n========== 图书管理系统 ==========");
System.out.println("1. 添加图书");
System.out.println("2. 删除图书");
System.out.println("3. 修改图书");
System.out.println("4. 查询图书");
System.out.println("5. 退出系统");
System.out.println("================================");
System.out.print("请选择操作 (1-5): ");
int choice;
try {
choice = Integer.parseInt(scanner.nextLine());
} catch (NumberFormatException e) {
System.out.println("输入无效,请输入数字 1-5。");
continue;
}
switch (choice) {
case 1:
addBook();
break;
case 2:
deleteBook();
break;
case 3:
updateBook();
break;
case 4:
queryBooks();
break;
case 5:
System.out.println("感谢使用,系统已退出。");
return; // 退出循环,结束程序
default:
System.out.println("无效的选择,请重新输入。");
}
}
}
private void addBook() {
System.out.println("--- 添加图书 ---");
System.out.print("请输入书名: ");
String title = scanner.nextLine();
System.out.print("请输入作者: ");
String author = scanner.nextLine();
System.out.print("请输入价格: ");
double price = Double.parseDouble(scanner.nextLine());
System.out.print("请输入库存: ");
int stock = Integer.parseInt(scanner.nextLine());
Book book = new Book(title, author, price, stock);
if (bookDao.addBook(book)) {
System.out.println("图书添加成功!");
} else {
System.out.println("图书添加失败!");
}
}
private void deleteBook() {
System.out.println("--- 删除图书 ---");
System.out.print("请输入要删除的图书ID: ");
int id = Integer.parseInt(scanner.nextLine());
if (bookDao.deleteBook(id)) {
System.out.println("图书删除成功!");
} else {
System.out.println("删除失败,可能图书ID不存在。");
}
}
private void updateBook() {
System.out.println("--- 修改图书 ---");
System.out.print("请输入要修改的图书ID: ");
int id = Integer.parseInt(scanner.nextLine());
Book book = bookDao.getBookById(id);
if (book == null) {
System.out.println("未找到ID为 " + id + " 的图书。");
return;
}
System.out.println("当前图书信息: " + book);
System.out.print("请输入新的书名 (直接回车保持不变): ");
String title = scanner.nextLine();
if (!title.isEmpty()) book.setTitle(title);
System.out.print("请输入新的作者 (直接回车保持不变): ");
String author = scanner.nextLine();
if (!author.isEmpty()) book.setAuthor(author);
System.out.print("请输入新的价格 (直接回车保持不变): ");
String priceStr = scanner.nextLine();
if (!priceStr.isEmpty()) book.setPrice(Double.parseDouble(priceStr));
System.out.print("请输入新的库存 (直接回车保持不变): ");
String stockStr = scanner.nextLine();
if (!stockStr.isEmpty()) book.setStock(Integer.parseInt(stockStr));
if (bookDao.updateBook(book)) {
System.out.println("图书信息更新成功!");
} else {
System.out.println("图书信息更新失败!");
}
}
private void queryBooks() {
System.out.println("--- 查询图书 ---");
System.out.println("1. 查询所有图书");
System.out.println("2. 按ID查询");
System.out.println("3. 按书名模糊查询");
System.out.print("请选择查询方式 (1-3): ");
int choice = Integer.parseInt(scanner.nextLine());
switch (choice) {
case 1:
List<Book> allBooks = bookDao.getAllBooks();
printBookList(allBooks);
break;
case 2:
System.out.print("请输入图书ID: ");
int id = Integer.parseInt(scanner.nextLine());
Book book = bookDao.getBookById(id);
if (book != null) {
System.out.println(book);
} else {
System.out.println("未找到该ID的图书。");
}
break;
case 3:
System.out.print("请输入书名关键字: ");
String keyword = scanner.nextLine();
List<Book> foundBooks = bookDao.findBooksByTitle(keyword);
printBookList(foundBooks);
break;
default:
System.out.println("无效的选择。");
}
}
private void printBookList(List<Book> books) {
if (books.isEmpty()) {
System.out.println("没有找到任何图书。");
} else {
System.out.println("------------------------------");
System.out.printf("%-5s %-20s %-15s %-10s %-10s\n", "ID", "书名", "作者", "价格", "库存");
System.out.println("------------------------------");
for (Book b : books) {
System.out.printf("%-5d %-20s %-15s %-10.2f %-10d\n",
b.getId(), b.getTitle(), b.getAuthor(), b.getPrice(), b.getStock());
}
System.out.println("------------------------------");
}
}
}
Main (程序入口)
Main.java
这是应用程序的启动类,负责创建 BookController 并启动主菜单。
package com.example.library;
import com.example.library.controller.BookController;
public class Main {
public static void main(String[] args) {
// 创建控制器实例并启动程序
BookController controller = new BookController();
controller.showMenu();
}
}
第六步:运行和测试
- 配置数据库连接: 打开
DBUtil.java文件,将USER和PASSWORD修改为你自己的 MySQL 用户名和密码。 - 编译运行: 在你的 IDE 中,直接运行
Main.java的main方法。 - 测试: 根据控制台提示,依次测试所有功能:
- 添加: 输入 1,然后按照提示输入一本新书的信息。
- 查询所有: 输入 4,然后选择 1,查看是否能看到刚才添加的书。
- 按ID查询: 输入 4,选择 2,输入刚添加的书的ID。
- 按书名查询: 输入 4,选择 3,输入书名中的关键字。
- 修改: 输入 3,输入书的ID,然后修改其中一些信息。
- 删除: 输入 2,输入书的ID。
- 退出: 输入 5。
总结与改进
这个图书管理系统是一个很好的 Java 和 JDBC 练习项目,它清晰地展示了 MVC 架构的应用。

可以进一步改进的方向:
- 图形用户界面: 将控制台界面替换为 Swing 或 JavaFX,提供更友好的用户交互。
- 异常处理: 增强对用户输入和数据库操作的异常处理,使程序更健壮。
- 分页查询: 当图书数量很多时,实现分页查询功能。
- 借阅功能: 增加一个
users表和borrows表,实现用户管理和图书借阅/归还功能。 - 日志记录: 使用 Log4j 或 SLF4J 等日志框架记录系统运行情况,方便排查问题。
- 连接池: 使用 HikariCP 等数据库连接池来管理数据库连接,提高性能和稳定性。
- 框架升级: 使用 Spring Boot 框架来重构项目,可以极大地简化配置和开发流程,是目前业界的主流选择。
