Java 图书管理系统实战:MySQL 与 JDBC 开发详解

落日邮差
落日邮差
发布时间:2026-10-16 | 4人浏览过
原创

本文基于 MySQL 和 Java 实现一个具备多角色权限(管理员与普通用户)的简易图书管理系统。核心内容包括使用 JdbcTemplate 或原生 JDBC 操作数据库、ORM 实体映射、DAO 层业务逻辑封装,以及利用抽象类和接口实现不同用户的菜单切换。

一、梳理功能需求

在设计系统前,需明确书籍数据模型、用户体系及各自的操作权限:

  1. 书籍信息实体:包含序号、书名、作者、价格、分类状态等字段。
  2. 用户角色:分为普通用户和管理员,两者拥有的操作菜单不同。
  3. 功能划分:
    • 普通用户:支持查看书籍列表、查找指定书籍、借书、还书。
    • 管理员:除了常规查询外,新增删除书籍的管理权限。

二、准备 MySQL 数据库

首先创建名为 java100_bookmanager 的数据库,分别定义书籍表 (book) 和用户表 (user)。初始化部分测试数据以便于调试。

create database if not exists java100_bookmanager;
use java100_bookmanager;
drop table if exists book;
-- 设置id为自增主键
create table book(id int primary key auto_increment,name varchar(20),author varchar(20),price int,type varchar(20),isBorrowed int);

drop table if exists user;
-- userId为自增主键,用户名唯一约束
create table user(
    userId int primary key auto_increment,
    username varchar(20) unique,
    password varchar(20),
    isAdmin int
);
-- 插入测试书籍
insert into book values(null,'西游记','吴承恩',10000,'古典小说',0);
insert into book values(null,'三国演义','罗贯中',10000,'古典小说',0);
insert into book values(null,'水浒传','施耐庵',10000,'古典小说',0);
insert into book values(null,'金瓶梅','兰陵笑笑生',10000,'古典小说',0);
-- 插入测试用户 (admin为管理员,普通用户为0)
insert into user values(null,'admin','123',1);
insert into user values(null,'zhangsan','123',0);

三、构造与数据库相关的实体类

书籍实体 (Books)

将数据库中的列映射为 Java 对象属性,并提供 Getter/Setter 方法。

public class Books {
    private int bookId;
    private String name;
    private String author;
    private int price;
    private String type;
    private boolean isBorrowed; //是否被借阅
    // Setters & Getters ...
}

用户体系设计

利用多态特性设计用户基类。AbstractUser 持有操作数组 (IOperation[] operations) 并定义执行操作的模板方法。管理员与普通用户继承该类并重写不同的菜单输出。

abstract public class AbstractUser {
    private int userId;
    private String userName;
    private String passWord;
    IOperation[] operations;

    abstract int menu(); // 抽象方法:各子类返回自己的菜单逻辑

    public void doOperation(int choice){
        operations[choice].work();
    }
    // ... Getter and Setter ...
}

普通用户类 (NormalUser)

实例化操作集合,限定其只能调用查看、搜索、借阅、归还等功能。

public class NormalUser extends AbstractUser {
    public NormalUser(){
        this.operations=new IOperation[]{
                new ExitOperation(), new DisplayOperation(), 
                new FindOperation(), new BorrowOperation(), new ReturnOperation()
        };
    }
    @Override
    public int menu() {
        System.out.println("欢迎您,"+this.getUserName()+"!");
        System.out.println("1.查看书籍列表\n2.查找指定书籍\n3.借阅书籍\n4.归还书籍\n0.退出系统");
        Scanner sc=new Scanner(System.in);
        return sc.nextInt();
    }
}

管理员类 (Admin)

相比普通用户,额外赋予了书籍的新增与删除操作。

public class Admin extends AbstractUser {
    public Admin(){
        this.operations=new IOperation[]{
                new ExitOperation(), new DisplayOperation(), 
                new FindOperation(), new AddOperation(), new DelOperation()
        };
    }
    @Override
    public int menu() {
        System.out.println("欢迎您,"+this.getUserName()+"!您是管理员");
        System.out.println("1.查看书籍列表\n2.查找指定书籍\n3.新增书籍\n4.删除书籍\n0.退出系统");
        Scanner sc=new Scanner(System.in);
        return sc.nextInt();
    }
}

四、封装数据库相关操作

采用 DAO (Data Access Object) 模式隔离数据库操作细节。

数据库连接管理 (DBUtil)

封装 DataSource 的懒汉式初始化。注意:实际生产环境中密码不应硬编码,建议从配置文件读取。

public class DBUtil {
    private static final String URL="jdbc:mysql://127.0.0.1:3306/java100_bookmanager?characterEncoding=utf8&&useSSL=false";
    private static final String USERNAME="root";
    private static final String PASSWORD="your_password";

    private static DataSource dataSource = null;

    public static DataSource getDataSource(){
        if(dataSource==null){
            try { 
                dataSource = new MysqlDataSource(); 
                ((MysqlDataSource)dataSource).setUrl(URL);
                ((MysqlDataSource)dataSource).setUser(USERNAME);
                ((MysqlDataSource)dataSource).setPassword(PASSWORD);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return dataSource;
    }

    public static Connection getConnection() throws SQLException {
        return getDataSource().getConnection();
    }

    // 统一资源释放方法
    public static void close(ResultSet resultSet, PreparedStatement statement, Connection connection){
        try {
            if(resultSet!=null) resultSet.close();
            if(statement!=null) statement.close();
            if(connection!=null) connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

书籍表操作 (BookDAO)

封装对 book 表的 CRUD 逻辑。以“添加”和“借阅”为例:

public class BookDAO {
    // 1. 新增书籍
    public boolean add(Books book){
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn = DBUtil.getConnection();
            String sql="insert into book values(null, ?, ?, ?, ?, ?)";
            ps=conn.prepareStatement(sql);
            ps.setString(1,book.getName());
            ps.setString(2,book.getAuthor());
            ps.setInt(3,book.getPrice());
            ps.setString(4,book.getType());
            ps.setInt(5,book.isBorrowed()?1:0);
            return ps.executeUpdate() == 1;
        } catch (SQLException e) { e.printStackTrace(); return false; }
        finally { DBUtil.close(null,ps,conn); }
    }

    // 5. 借阅书籍
    public boolean borrowBook(int bookId){
        Connection conn = null;
        PreparedStatement selectPs = null;
        PreparedStatement updatePs = null;
        ResultSet rs = null;
        try {
            conn = DBUtil.getConnection();
            // 检查该书是否存在且未被借出
            String checkSql = "select isBorrowed from book where id=?";
            selectPs=conn.prepareStatement(checkSql);
            selectPs.setInt(1, bookId);
            rs = selectPs.executeQuery();
            if(!rs.next()) {
                System.out.println("该书籍不存在");
                return false;
            }
            if(rs.getInt("isBorrowed") == 1) {
                System.out.println("此书已被借出");
                return false;
            }
            // 更新状态
            String updateSql = "update book set isBorrowed=1 where id=?";
            updatePs=conn.prepareStatement(updateSql);
            updatePs.setInt(1, bookId);
            return updatePs.executeUpdate() == 1;
        } catch (SQLException e) { e.printStackTrace(); return false; }
        finally { DBUtil.close(rs,selectPs,conn); }
    }
}

用户表操作 (UserDao)

根据传入的用户名查询用户信息,并根据管理员标识 (isAdmin) 动态实例化对应类型的 User 对象。

public class UserDao {
    public AbstractUser selectByName(String name){
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            conn=DBUtil.getConnection();
            String sql="select * from user where username=?";
            ps = conn.prepareStatement(sql);
            ps.setString(1, name);
            rs = ps.executeQuery();
            if(rs.next()){
                boolean isAdmin=(rs.getInt("isAdmin")==1);
                AbstractUser user = isAdmin ? new Admin() : new NormalUser();
                user.setPassWord(rs.getString("password"));
                user.setUserId(rs.getInt("userId"));
                user.setUserName(rs.getString("username"));
                return user;
            }
        } catch (SQLException e) { e.printStackTrace(); }
        finally { DBUtil.close(rs,ps,conn); }
        return null;
    }
}

五、编写主程序入口与业务逻辑

登录模块与循环调度

在 Main 类中实现启动流程:先验证登录凭证,获取对应的 AbstractUser 实例后,进入死循环等待用户输入选择。

public class Main {
    public static void main(String[] args) {
        AbstractUser currentUser = login();
        while(true){
            int choice = currentUser.menu();
            currentUser.doOperation(choice);
        }
    }

    private static AbstractUser login(){
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入用户名: ");
        String name = sc.next();
        System.out.print("请输入密码: ");
        String password = sc.next();
        
        UserDao userDao = new UserDao();
        AbstractUser user = userDao.selectByName(name);
        if(user == null){
            System.out.println("用户不存在,程序退出");
            System.exit(0);
        }
        if(!user.getPassWord().equals(password)){
            System.out.println("密码错误,程序退出");
            System.exit(0);
        }
        return user;
    }
}

业务操作类实现 (Operations)

所有具体业务动作均实现统一的 IOperation 接口。

// 通用接口定义
public interface IOperation {
    void work();
}

// 示例:显示所有书籍
public class DisplayOperation implements IOperation {
    @Override
    public void work() {
        System.out.println("展示所有书籍:");
        BookDAO bookdao = new BookDAO();
        List<Books> list = bookdao.selectAll();
        for(Books b : list) {
            System.out.println(b);
        }
    }
}

// 示例:退出系统
public class ExitOperation implements IOperation {
    @Override
    public void work() {
        System.out.println("感谢使用,退出程序");
        System.exit(0);
    }
}

六、总结

本案例通过构建命令行版的图书管理系统,串讲了 Java 面向对象的设计思想以及后端开发的基石——JDBC。通过 DAO 层的解耦以及多态机制的应用,代码结构清晰,易于后续扩展。以上就是 Java 图书管理系统结合 MySQL 与 JDBC 的详细内容,更多关于 Java 实战项目开发的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表