Java银行管理系统实战:从MySQL建表到Swing界面完整方案

发布时间:2026/10/9 16:12:48

Java银行管理系统实战:从MySQL建表到Swing界面完整方案 简介这是一套面向Java初学者与课程设计学习者的银行管理系统项目源码基于IntelliJ IDEA开发采用Java Swing构建图形界面以MySQL作为后台数据存储实现管理员与顾客两类角色的完整业务闭环。管理员可登录、添加或删除顾客、统计存储金额顾客可完成登录、存款、取款、转账、修改密码、查看交易记录及安全退出适合作为Java面向对象编程、数据库应用与Swing界面开发的综合练习素材。资源包为rar压缩格式共28个文件约40KB包含14个class编译文件、6个xml与2个yml配置、2个html页面、1个java源码及1个md说明文档覆盖项目配置、界面资源与核心逻辑目录结构清晰便于快速导入IDEA运行调试。目前已有424人学习浏览读者可借此理解银行系统的模块划分、身份验证与交易处理流程积累数据库连接、异常处理与界面交互的实战经验为后续金融类软件开发打下基础。1. Java 银行管理系统从建表到 Swing 界面一套能跑起来的桌面端方案很多人第一次做 Java 银行管理系统卡住的地方不是业务逻辑而是环境。IDEA 装好了MySQL 也装好了结果 JDBC 驱动没导进去或者 Swing 窗口一运行就报NullPointerException。这套系统本质上是一个桌面端 CRUD 应用JavaSwing 负责界面MySQL 负责持久化IDEA 负责开发和调试。它适合两类人——正在找 Java 课程设计题目的学生以及想用一个小项目把 JDBC、Swing 事件模型、事务处理串起来的初级开发者。核心难点不在代码量而在三层结构怎么分、连接怎么管、界面和数据库怎么同步。下面按建库、连库、写界面、排错的顺序把每一步拆开讲。2. 建库与建表先把 MySQL 这边的地基打牢2.1 银行系统需要哪几张表一个能跑通的银行管理系统最少需要四张表用户表、账户表、交易记录表、管理员表。用户表和账户表分开是因为一个用户可能持有多个账户这是银行系统的基本模型。交易记录表只增不改保证流水可追溯。-- 创建数据库字符集用 utf8mb4避免中文乱码 CREATE DATABASE bank_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE bank_system; -- 用户表存客户基本信息 CREATE TABLE t_user ( user_id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, -- 存 MD5 或 SHA-256不存明文 real_name VARCHAR(50) NOT NULL, phone VARCHAR(20), create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 账户表一个用户可以有多个账户 CREATE TABLE t_account ( account_id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, card_no VARCHAR(19) NOT NULL UNIQUE, -- 卡号 balance DECIMAL(15,2) DEFAULT 0.00, -- 金额必须用 DECIMAL status TINYINT DEFAULT 1, -- 1 正常 0 冻结 FOREIGN KEY (user_id) REFERENCES t_user(user_id) ); -- 交易记录表只插入不更新 CREATE TABLE t_transaction ( trans_id INT PRIMARY KEY AUTO_INCREMENT, card_no VARCHAR(19) NOT NULL, trans_type VARCHAR(10) NOT NULL, -- 存款/取款/转账 amount DECIMAL(15,2) NOT NULL, trans_time DATETIME DEFAULT CURRENT_TIMESTAMP, remark VARCHAR(100) );金额字段用DECIMAL(15,2)而不是FLOAT或DOUBLE这是血泪经验。浮点数在累加时会出现0.1 0.2 0.30000000000000004这类问题银行系统里一分钱都不能差。密码字段长度给 64是因为 SHA-256 输出是 64 位十六进制字符串如果只存 MD5 给 32 位就够但建议直接上 SHA-256。2.2 在 IDEA 里连上 MySQL打开 IDEA右侧 Database 面板点加号选 MySQL。Host 填localhostPort 填3306Database 填bank_system。第一次连接会提示下载驱动点 Download 就行。如果连不上先确认 MySQL 服务在跑# Windows 下检查 MySQL 服务状态 net start | findstr mysql # 如果没启动手动启动 net start mysql80连接成功后IDEA 的 Database 面板能直接看到四张表后面写代码时字段名不用来回切窗口查。这里有个细节MySQL 8.0 的驱动类名是com.mysql.cj.jdbc.Driver5.7 是com.mysql.jdbc.Driver。用错会报ClassNotFoundException这是新手最常见的翻车点之一。2.3 JDBC 工具类的写法不要在每个 DAO 里都写一遍DriverManager.getConnection。抽一个工具类出来统一管理连接参数。public class DBUtil { // MySQL 8.0 必须加时区参数否则报时区错误 private static final String URL jdbc:mysql://localhost:3306/bank_system?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 你的密码; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { throw new RuntimeException(MySQL 驱动未导入, e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } // 关闭资源顺序不能反先关 ResultSet再关 Statement最后关 Connection public static void close(Connection conn, Statement stmt, ResultSet rs) { try { if (rs ! null) rs.close(); } catch (SQLException ignored) {} try { if (stmt ! null) stmt.close(); } catch (SQLException ignored) {} try { if (conn ! null) conn.close(); } catch (SQLException ignored) {} } }serverTimezoneAsia/Shanghai这个参数不加MySQL 8.0 会直接抛The server time zone value ?D1ú±ê×?ê±?? is unrecognized。useSSLfalse是本地开发关掉 SSL 警告生产环境要开。characterEncodingutf8保证中文能正确写入。3. Swing 界面用最少组件搭出可用的操作台3.1 登录窗口和主窗口怎么分Swing 的坑在于布局管理器。很多人一上来用绝对定位setBounds换个分辨率就全乱。正确做法是用BorderLayout做外层GridBagLayout或GridLayout做表单区。登录窗口只放三个东西用户名输入框、密码输入框、登录按钮。主窗口用JTabbedPane分页把存款、取款、转账、查询流水分成四个 Tab每个 Tab 里放一个独立的JPanel。public class LoginFrame extends JFrame { private JTextField userField; private JPasswordField passField; public LoginFrame() { setTitle(银行管理系统 - 登录); setSize(400, 250); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); // 居中显示 JPanel panel new JPanel(new GridBagLayout()); GridBagConstraints gbc new GridBagConstraints(); gbc.insets new Insets(8, 8, 8, 8); // 组件间距 gbc.gridx 0; gbc.gridy 0; panel.add(new JLabel(用户名), gbc); gbc.gridx 1; userField new JTextField(15); panel.add(userField, gbc); gbc.gridx 0; gbc.gridy 1; panel.add(new JLabel(密码), gbc); gbc.gridx 1; passField new JPasswordField(15); panel.add(passField, gbc); gbc.gridx 0; gbc.gridy 2; gbc.gridwidth 2; JButton loginBtn new JButton(登录); loginBtn.addActionListener(e - doLogin()); panel.add(loginBtn, gbc); add(panel); setVisible(true); } private void doLogin() { String username userField.getText().trim(); String password new String(passField.getPassword()); // 这里调 Service 层验证不要直接写 SQL UserService service new UserService(); User user service.login(username, password); if (user ! null) { dispose(); // 关掉登录窗 new MainFrame(user); // 打开主窗口 } else { JOptionPane.showMessageDialog(this, 用户名或密码错误); } } }setLocationRelativeTo(null)让窗口在屏幕居中不加这行窗口会跑到左上角。GridBagConstraints的insets控制组件间距不设的话按钮和输入框会挤在一起。登录逻辑里不要直接写 SQL调 Service 层这样后面换数据库或加缓存不用改界面代码。3.2 存款取款的事件处理与事务存款和取款的核心是事务。取款要先查余额够才能扣扣完要写流水。这三步必须在同一个事务里否则可能出现扣了钱没写流水的情况。public class AccountService { public boolean withdraw(String cardNo, BigDecimal amount) { Connection conn null; PreparedStatement ps null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 开启事务 // 第一步查余额加行锁防止并发扣款 String querySql SELECT balance FROM t_account WHERE card_no ? FOR UPDATE; ps conn.prepareStatement(querySql); ps.setString(1, cardNo); ResultSet rs ps.executeQuery(); if (!rs.next()) { conn.rollback(); return false; } BigDecimal balance rs.getBigDecimal(balance); if (balance.compareTo(amount) 0) { conn.rollback(); return false; // 余额不足 } // 第二步扣款 String updateSql UPDATE t_account SET balance balance - ? WHERE card_no ?; ps conn.prepareStatement(updateSql); ps.setBigDecimal(1, amount); ps.setString(2, cardNo); ps.executeUpdate(); // 第三步写流水 String insertSql INSERT INTO t_transaction(card_no, trans_type, amount) VALUES(?, 取款, ?); ps conn.prepareStatement(insertSql); ps.setString(1, cardNo); ps.setBigDecimal(2, amount); ps.executeUpdate(); conn.commit(); return true; } catch (SQLException e) { try { if (conn ! null) conn.rollback(); } catch (SQLException ignored) {} e.printStackTrace(); return false; } finally { DBUtil.close(conn, ps, null); } } }FOR UPDATE是行级锁防止两个线程同时查到相同余额然后都扣款。setAutoCommit(false)开启事务后任何一步失败都要rollback。BigDecimal的compareTo返回 -1、0、1不能用equals因为equals会比较精度1.0和1.00不相等。3.3 表格刷新与界面同步Swing 的JTable不会自动感知数据库变化。存款成功后界面上的余额标签和流水表格要手动刷新。// 刷新流水表格 DefaultTableModel model (DefaultTableModel) transTable.getModel(); model.setRowCount(0); // 清空旧数据 ListTransaction list transService.getByCardNo(cardNo); for (Transaction t : list) { model.addRow(new Object[]{t.getTransTime(), t.getTransType(), t.getAmount(), t.getRemark()}); }setRowCount(0)清空表格然后重新查库填充。不要在 Swing 的事件线程里做耗时查询数据量大时界面会卡死。常见做法是开一个SwingWorker在后台查查完再publish到表格。小项目数据量小直接查也能接受但要知道这个边界。4. 避坑与排查那些让项目跑不起来的细节4.1 驱动导入后仍然报 ClassNotFoundException现象IDEA 里已经 Add as Library 了运行还是报ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因jar 包加到了模块依赖但没加到 Artifact 的输出里。IDEA 运行 Java 应用时最终用的是编译输出目录不是模块依赖列表。解决File → Project Structure → Artifacts → 选中当前模块 → 在右侧 Available Elements 里双击 mysql-connector-java把它加到输出根目录下。或者直接用 Maven 管理依赖在pom.xml里加dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependencyMaven 会自动处理依赖传递和打包比手动导 jar 省心。4.2 中文写入数据库变成问号现象Swing 界面输入中文姓名存进 MySQL 后变成???。原因三个环节的字符集不一致——数据库、连接 URL、表字段。任何一处不是 utf8中文就会丢。解决建库时指定utf8mb4连接 URL 加characterEncodingutf8表字段用VARCHAR而不是CHAR。如果已经建了表用ALTER TABLE t_user CONVERT TO CHARACTER SET utf8mb4;改。另外 MySQL 8.0 默认字符集已经是 utf8mb45.7 需要手动指定。4.3 Swing 窗口关闭后进程不退出现象点了窗口右上角的 X窗口关了但 IDEA 的运行按钮还是红的进程没结束。原因JFrame默认的关闭操作是HIDE_ON_CLOSE只是隐藏窗口没有释放资源。如果开了线程或连接池进程会一直挂着。解决setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)让关闭窗口时退出 JVM。如果有未关闭的数据库连接在windowClosing事件里手动关掉。更稳妥的做法是加一个WindowAdapteraddWindowListener(new WindowAdapter() { Override public void windowClosing(WindowEvent e) { // 关闭连接池等资源 System.exit(0); } });4.4 转账时两边余额不一致现象A 账户扣了钱B 账户没加钱或者两边都加了。原因转账涉及两条 UPDATE没有放在同一个事务里或者事务中途抛异常没有回滚。解决转账必须在一个Connection里完成setAutoCommit(false)两条 UPDATE 都成功后commit任何一步失败rollback。不要用两个 Service 方法各开各的连接那样事务控制不住。常见做法是把转账逻辑写在一个方法里共用同一个Connection。4.5 IDEA 运行报 cannot start internal http server现象IDEA 启动时弹窗报Cannot start internal HTTP server项目能编译但运行不了。原因端口被占用通常是 63342 端口被其他程序占了或者 IDEA 的缓存坏了。解决先重启 IDEA不行就 File → Invalidate Caches → Invalidate and Restart。再不行检查 63342 端口netstat -ano | findstr 63342找到占用进程的 PID在任务管理器里结束掉。这个报错和项目代码无关是 IDEA 自身的问题不用改代码。5. 进阶技巧用 MyBatis-Plus 反向生成实体类少写一半代码手写 DAO 层是体力活。表字段一多ResultSet的getString、getInt写到手酸。MyBatis-Plus 的代码生成器能根据表结构直接生成实体类、Mapper、Service省掉大量重复代码。这不是必须的但用过就回不去了。在pom.xml里加依赖dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.5/version /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-generator/artifactId version3.5.5/version /dependency写一个生成器类public class CodeGenerator { public static void main(String[] args) { FastAutoGenerator.create( jdbc:mysql://localhost:3306/bank_system?serverTimezoneAsia/Shanghai, root, 你的密码) .globalConfig(builder - builder .author(yourname) .outputDir(System.getProperty(user.dir) /src/main/java)) .packageConfig(builder - builder .parent(com.bank) .entity(entity) .mapper(mapper) .service(service)) .strategyConfig(builder - builder .addInclude(t_user, t_account, t_transaction) // 指定表名 .entityBuilder() .enableLombok() // 用 Lombok 省掉 getter/setter .enableTableFieldAnnotation()) .execute(); } }跑一次main方法entity、mapper、service三个包自动生成。enableLombok()需要项目里已经引入 Lombok 依赖否则生成的Data注解会报错。addInclude指定要生成的表不写会生成库里所有表包括你不想要的。生成后的实体类长这样Data TableName(t_account) public class Account { TableId(value account_id, type IdType.AUTO) private Integer accountId; TableField(user_id) private Integer userId; TableField(card_no) private String cardNo; TableField(balance) private BigDecimal balance; TableField(status) private Integer status; }TableName映射表名TableId指定主键和自增策略TableField映射字段名。有了这些注解MyBatis-Plus 的BaseMapper直接提供selectById、insert、updateById、deleteById等方法不用手写 SQL。转账那种复杂事务还是得自己写但单表 CRUD 基本不用碰 SQL 了。一个验证技巧生成完代码后先写一个测试方法调accountMapper.selectList(null)能查出数据说明映射没问题。查不出来先看表名和字段名是否匹配MyBatis-Plus 默认开启驼峰转下划线accountId对应account_id如果表字段是accountid就会映射失败。我自己的习惯是新项目先用生成器把实体和 Mapper 生成出来再在 Service 层写业务逻辑。这样能把精力放在事务控制和界面交互上而不是纠结字段名拼写。数据库连接参数和密码不要硬编码在代码里放到application.properties或环境变量里这是从第一天就该养成的习惯。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/9 16:12:48

Binary Ninja Python插件开发:从零实现自动化逆向分析

简介:这份资源是面向逆向工程与二进制安全方向的 Python 开发者整理的 Binary Ninja 插件开发资料包,适合已具备一定 Python 基础、希望借助脚本扩展反汇编分析流程的安全研究员与软件开发者。包内共 6 个文件,以 py 脚本、json 配置、yaml 参…

2026/10/9 16:12:48

Windows 64位下编译Qt与Tesseract OCR库及集成指南

简介:本资源为面向 Windows 64 位平台的 Tesseract OCR 编译产物,专为使用 Qt 进行桌面端文字识别开发的工程师准备,可解决在 Windows 环境下自行编译 Tesseract 依赖繁琐、版本兼容困难的问题。压缩包共 916 个文件,约 39.32MB&a…

2026/10/9 16:12:48

dnSpy-net472:专为.NET Framework 4.7.2设计的调试与热重载逆向工具

简介:dnSpy-net472.zip 是一款面向.NET开发者、逆向分析人员及安全研究人员的实用工具包,专为.NET Framework 4.7.2环境下的DLL反编译、源码级调试与二进制编辑提供一体化支持。资源包含x86架构主程序dnSpy-x86.exe、配套PDB调试文件、运行配置文件&…

2026/10/9 17:08:09

HDFS读写流程与常用操作实战:从命令到避坑指南

简介:这份资源是《大数据技术原理与应用》课程实验二的完整报告文档,面向正在学习Hadoop与大数据基础的高校学生及自学者,帮助解决HDFS Shell命令与Java API操作入门难、实验流程不清晰的问题。压缩包内仅含1个docx文件,约3.4MB&a…

2026/10/9 17:08:09

Windows下Oracle 12.2.0.1数据库OPatch升级避坑指南

简介:这是适用于64位 Windows 的 Oracle OPatch 12.2.0.1.40 工具包,面向 Oracle 数据库管理员与运维人员,用于在 Oracle Database 12c Release 2 环境中安装、卸载和验证补丁。资源共456个文件,压缩包大小108.1MB,包含…

2026/10/9 17:08:09

中文情感分析实战:WeiboSenti100k与BERT微调工程指南

简介:这份资源是一套面向计算机、人工智能及相关专业学生的中文情感分析实战方案,以WeiboSenti100k微博评论语料为基础,结合预训练语言模型BERT进行针对性微调,可用于课程设计、学期项目或毕业设计参考,帮助学习者打通…

2026/10/9 17:08:09

dnSpy 6.1.3 net472 反编译调试修改程序集实战指南

简介:dnSpy 6.1.3 是一款面向 .NET 开发者的集成反编译、调试与代码编辑工具,基于 .NET Framework 4.7.2 构建,适用于 Windows 环境。这套 zip 压缩包整体约 22.37MB,内含主程序、x86/x64 双版本可执行文件、命令行控制台版本及配…

2026/10/9 17:08:09

老鼠走迷宫:用栈实现深度优先搜索的原理与实践

1. 项目概述:为什么一个“老鼠走迷宫”能讲透栈的本质你翻过《数据结构》教材第3章,看到“栈”这个概念——后进先出、入栈出栈、括号匹配、表达式求值……概念都懂,可一合上书,脑子里还是空的。直到某天在实验室调试一个迷宫求解…

2026/10/9 17:03:07

T3Code代码成熟度模型:从能跑到能演化的质量提升指南

今天想聊一个很多团队都会卡住的命题:代码能跑,然后呢?我见过太多项目,线上没崩、接口能通、功能全上了,但稍微加点需求,改动一个字段要翻三四个文件;新同学入职两周,代码看懂了三分…

2026/10/8 10:03:18

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/8 10:03:20

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 0:04:27

毕业论文初稿完成后首次进行AIGC疑似度自查的摸底与分流策略

毕业论文初稿完成后首次进行AIGC疑似度自查的摸底与分流策略当数万字的学位论文初稿经历开题、实验、问卷与多轮文献梳理最终成形时,绝大多数研究生都会面临一道全新的形式审查关卡:AIGC 疑似度排查。在高校毕业审核流程中,盲审前的文本检测通…

2026/10/9 0:04:27

食堂节能改造源头工厂,商用厨房设备焕新方案广受好评

商用厨房作为餐饮经营、单位供餐的核心后勤阵地,其设备配置、动线规划与运维体系直接决定后厨作业效率、运营成本与合规性。从基础的灶具、制冷存储设备,到油烟净化、水处理等配套系统,每一个环节的合理性都与食品安全、能耗管控、消防安全挂…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑