资讯动态

Java Swing+Oracle飞机订票系统开发实战:从ER图到JDBC事务

发布时间:2026/9/8 11:50:04 来源:尧图企业网站定制
简介这是一套基于Java Swing和Oracle数据库的飞机订票系统完整项目资源适合正在学习Java GUI编程、Oracle数据库设计以及软件工程课程项目的开发者参考。资源提供了从需求分析、数据库建模到界面实现、业务流程梳理的完整链路可以帮助读者快速掌握桌面订票系统的开发方法。压缩包共303个文件大小约104.73MB包括Java源码与编译后的class文件、项目所需的jar库、PPT讲解、ER图、流程图、SQL建表脚本以及运行演示视频和说明文档。其中ER图展示了航班、乘客、订单等实体关系流程图清晰呈现登录、查询、预订、支付等关键环节方便对照源码理解业务逻辑。目前已有400人学习下载对于需要完成课程设计或想系统了解SwingOracle整合开发的学习者来说是一份内容详实、可直接跟练的参考资料。 又到一年毕业季Java Swing配合Oracle做飞机订票系统几乎是每个计算机专业学生绕不开的经典选题。这个题目好在技术栈非常标准Swing负责界面展示Oracle负责数据持久化ER图和流程图把整个系统的设计过程完整呈现出来答辩时老师问来问去也就那些点准备充分真不难。我自己带过好几届学弟学妹做这个题目今天就把从ER图设计到Swing落地、再到Oracle数据库连接的全过程拆开讲一遍包括表结构怎么建、订票事务怎么保证、绘图工具怎么选以及那些只有实际动手才会踩到的坑。1. 项目整体设计与需求拆解1.1 飞机订票系统到底在解决什么问题很多同学拿到这个题目第一反应是“做个界面连个数据库能增删改查就行”。这个理解太浅了。飞机订票系统表面上看是一个典型的管理信息系统但真正核心的点在于业务状态流转航班有起飞和时间座位有余量订单有状态待支付、已出票、已退票一次订票操作不是简单地往表里插一条记录而是要同时完成订单创建、乘客信息保存、航班余量扣减这三个动作。这个业务特征决定了系统设计时不能像学生管理系统那样随便来。如果你一开始就把表结构和代码层次理清楚后面窗口做起来反而快如果一上来就拖控件写代码等做到订票那一步十有八九要推倒重来。1.2 角色划分与功能清单飞机订票系统按使用者通常分成两类角色界面和功能都围绕这两个角色展开普通用户注册登录、航班查询、在线订票、退票改签、个人订单查看系统管理员航班信息维护、全部订单查询、基础数据统计、用户管理这个功能清单直接决定了项目的规模普通用户端大概需要5到6个窗口管理端需要3到4个窗口。功能再多就容易失控毕竟这是课程设计或毕设不是真的要做成12306。功能清单定了以后ER图的实体和流程图的核心路径也就有了依据。2. ER图设计先建模再写代码2.1 核心实体与Oracle建表要点飞机订票系统的ER图通常包含四个核心实体用户表、航班表、订单表、乘客信息表。用户表和订单表是一对多关系航班表和订单表也是一对多关系订单和乘客信息可以设计成一对一一个订单对应一个乘客也可以设计成一对多一个订单含多个乘客。课程设计建议一对一关系简化逻辑。Oracle建表和MySQL有个很大的区别Oracle没有MySQL那种AUTO_INCREMENT自增列需要靠**序列Sequence加触发器Trigger**来实现主键自增。这是答辩时老师最常问的一个点很多人在这里栽跟头。航班表的基本结构可以参考下面这种写法CREATE TABLE FLIGHT ( FLIGHT_ID NUMBER(10) PRIMARY KEY, FLIGHT_NO VARCHAR2(20) NOT NULL, DEPARTURE_CITY VARCHAR2(50) NOT NULL, ARRIVAL_CITY VARCHAR2(50) NOT NULL, DEPARTURE_TIME DATE NOT NULL, ARRIVAL_TIME DATE NOT NULL, TOTAL_SEATS NUMBER(5) NOT NULL, LEFT_SEATS NUMBER(5) NOT NULL, PRICE NUMBER(10,2) NOT NULL ); CREATE SEQUENCE SEQ_FLIGHT_ID START WITH 1 INCREMENT BY 1; CREATE OR REPLACE TRIGGER TRG_FLIGHT_ID BEFORE INSERT ON FLIGHT FOR EACH ROW BEGIN SELECT SEQ_FLIGHT_ID.NEXTVAL INTO :NEW.FLIGHT_ID FROM DUAL; END;这里有个细节需要注意VARCHAR2在Oracle中默认的长度单位是字节如果项目里涉及中文建议写成VARCHAR2(50 CHAR)这种形式避免因为中文字节数超出报错。日期字段千万要用DATE类型不要图省事存字符串不然后面想用TRUNC(SYSDATE)这类函数做日期比较会非常痛苦。2.2 表间关系与外键设计用户表和订单表的关系以及航班表和订单表的关系在ER图上要明确标出。订单表通常是三个实体里最核心的一张表它的外键设计会影响整条业务链路的代码写法我建议订单表这样设计ORDER_ID主键序列生成USER_ID外键关联用户表FLIGHT_ID外键关联航班表PASSENGER_NAME乘客姓名ID_CARD_NO证件号码ORDER_STATUS订单状态0待支付、1已出票、2已退票外键字段一定要在Oracle中建立索引否则当用户表或航班表数据量大了以后删除或修改父表记录时会导致外键约束检查全表扫描严重时会把数据库锁住。这个点很多入门教程不会提但实际开发中非常关键属于那种不遇到问题不知道重要性的细节。2.3 画ER图的工具选择绘制ER图的工具我比较推荐三个ProcessOn、draw.io、Navicat反向导入。前两个是画图工具适合从零开始设计Navicat有一个“逆向建模”功能可以把已经建好的Oracle表结构直接生成ER图导出的图形非常规范答辩前用这个检查遗漏特别方便。画ER图时建议遵循基本规范实体用矩形、属性用椭圆、关系用菱形但在PPT展示时可以更实用一些把每个表用卡片形式列出来表名放在顶部字段按主键、外键、普通字段分开放关系用连线加标注说明。这样的ER图老师看一眼就能明白设计思路。3. 流程图设计把业务流程画给老师看3.1 订票主流程拆解流程图是很多同学的薄弱环节总想着“流程就是那几个按钮有什么好画的”。实际上流程图的价值在于展示你对业务逻辑的理解。飞机订票系统的核心主流程是这样的用户输入用户名密码登录系统选择出发城市、到达城市、出发日期查询航班系统从数据库检索符合条件的航班列表并展示用户选择航班录入乘客姓名、证件号用户提交订单系统检查该航班余票是否充足余票不足则提示失败余票充足则创建订单、扣减余票支付成功课程设计可简化为直接确认后订单状态变为已出票画流程图的时候建议使用泳道图左侧泳道放用户操作中间放系统处理右侧放数据库操作。这样能清楚表达每个动作是谁发起的数据库在哪个节点做了读写比普通的单线流程图更清晰。工具上用Visio或者ProcessOn都可以ProcessOn的好处是模板多、可以直接导出高清图片放进PPT。3.2 退票流程与状态流转退票流程和订票流程是反向操作但容易漏掉关键一步退票成功时必须把航班余票加回来。状态流转可以这样定义待支付 → 支付成功 → 已出票 → 退票申请 → 已退票待支付状态超过一定时间可简化做自动取消画退票的泳道图时注意把“更新航班余票数”这个数据库操作明确标注出来。有些同学画退票流程图只画了订单状态从“已出票”改成“已退票”没有画余票回补答辩被老师追问时才发现业务逻辑不闭合。3.3 流程图排版与规范提醒画流程图最容易出现的问题是图形不规范判断框用了直角矩形、开始结束忘了用圆角矩形、箭头方向混乱。答辩时评委老师不一定会仔细看每一处符号但整体视觉感受会影响打分。建议统一风格所有流程图中相同含义的节点使用相同颜色和形状箭头直线连接关键判断处给出明确的“是/否”分支标注。这样整体排版干净老师一眼能看出你真正掌握了流程图的基本规范。4. Swing界面落地从登录页到订票页的完整链路4.1 层次分明地组织代码Swing项目最忌讳一句话逻辑全部堆在ActionListener里。哪怕功能简单我也建议在代码里建立清晰的包结构把界面和业务逻辑分开。一个比较舒服的分层方式是view包存放各个JFrame、JPanel界面类dao包存放数据库访问类负责SQL执行和结果集处理service包存放业务逻辑比如订票事务、余额校验util包存放数据库连接工具类、公共方法这样做的好处不只是结构好看更重要的是出现问题时好排查。比如订票失败你不用在界面代码里翻半天SQL语句直接去service层和dao层查逻辑就好。Swing界面代码本来就啰嗦如果再和数据库代码纠缠在一起后期调试会非常痛苦。4.2 登录、航班查询、订票三个核心窗口登录窗口是整个系统的入口一般包含用户名、密码两个输入框和一个登录按钮。这里有个实用的小技巧登录时除了查用户名密码是否匹配还可以把用户ID存到当前会话变量里比如一个全局的User对象后续订单操作都要用到这个ID避免每次都重新查询用户表。航班查询窗口是整个系统最核心的界面建议用JTable展示航班列表。JTable的数据填充通常使用DefaultTableModel把数据库查出来的ResultSet转换成Vector或二维数组塞进去。需要注意的坑是ResultSet用完之后要关掉但DefaultTableModel里的数据已经从ResultSet拷贝出来了不会因为连接关闭而丢失这个顺序不要搞混。订票窗口可以做成点击航班查询结果表格后弹出的子窗口上面显示所选航班的详细信息让用户填入乘客姓名和证件号确认后生成订单。这里要特别注意socket的反馈订票成功要提示“订票成功”失败要说明原因比如余票不足弹窗用JOptionPane.showMessageDialog即可不要自己写新的Frame当弹窗那是自找麻烦。4.3 Swing布局管理器与常见体验问题Swing的布局管理器是新手最容易翻车的地方。null布局加绝对坐标虽然拖控件方便但窗口一缩放就乱成一团答辩演示时常被老师当场放大窗口瞬间原形毕露。更推荐的方式是使用BorderLayout分工上下区域中间内容区用GridBagLayout做精细定位。GridBagLayout学起来有点门槛但掌握之后自由度非常高界面在不同分辨率下也能保持整齐。还有一个容易被忽略的是线程问题。Swing是单线程模型所有界面更新必须在事件调度线程EDT中执行。如果直接在ActionListener里执行数据库查询数据量小没事数据量大一点界面就会卡死。最简单的改进方式是用SwingWorker做后台查询查询完成后在done()方法里刷新界面。课程设计不用做得很复杂但能主动用SwingWorker处理耗时操作答辩时是明显加分项。5. JDBC连接Oracle配置和事务处理5.1 驱动、URL与连接池选择Java Swing连接Oracle用的是JDBC标准接口。驱动包选择ojdbc8.jar对应Oracle 12c及以上版本如果是Oracle 11g可以用ojdbc6.jar。驱动要放在项目的lib目录下并加入Build Path这一步很多同学忘记运行时报ClassNotFoundException才想起来。连接URL的标准写法是String url jdbc:oracle:thin://localhost:1521/ORCL; String username scott; String password tiger; Class.forName(oracle.jdbc.driver.OracleDriver); Connection conn DriverManager.getConnection(url, username, password);注意URL中后面可以是//主机:端口/服务名也可以是主机:端口:SID两种写法在部分版本有差异。如果连接报错提示“Oracle listener cannot recognize SID”把URL改成jdbc:oracle:thin:localhost:1521:ORCL这种老格式试试大概率能解决。实际项目里建议把数据库连接封装成一个工具类提供getConnection()和close()方法所有DAO层统一调用。这样换数据库地址或者改账号密码时只需要改一个地方不用满世界找DriverManager.getConnection。5.2 订票事务的原子性保证订票业务是关键事务场景核心要求是要么全部成功要么全部失败。教材上常讲的事务概念在这个项目里必须真正落地一次订票操作涉及三个写操作——插入订单记录、插入乘客信息、更新航班余票任何一步失败都不能让其他步骤生效。用JDBC实现事务控制的经典代码框架如下Connection conn null; try { conn DBUtil.getConnection(); conn.setAutoCommit(false); // 1. 插入订单记录 // 2. 插入乘客信息 // 3. 更新航班余票数额 conn.commit(); } catch (SQLException e) { if (conn ! null) { try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } } e.printStackTrace(); } finally { // 关闭资源 }这里有个实操心得setAutoCommit(false)之后一旦程序异常退出但没有调用rollback()数据库连接会一直攥着事务不放导致表被锁住。所以在catch里必须显式回滚finally里必须关闭连接。另外余票扣减的SQL最好写成条件更新例如UPDATE FLIGHT SET LEFT_SEATSLEFT_SEATS-1 WHERE FLIGHT_ID? AND LEFT_SEATS0受影响行数为0说明余票不足这样可以做到原子性的余票校验扣减避免两个人同时订最后一张票时出现超卖。5.3 PreparedStatement防SQL注入Swing客户端程序里用户的输入用户名、航班号、乘客姓名都需要拼接到SQL中执行这里强烈建议统一使用PreparedStatement的占位符写法不要用字符串拼接SQL。String sql SELECT * FROM FLIGHT WHERE DEPARTURE_CITY? AND ARRIVAL_CITY? AND TRUNC(DEPARTURE_TIME)?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, departure); ps.setString(2, arrival); ps.setDate(3, new java.sql.Date(date.getTime())); ResultSet rs ps.executeQuery();PreparedStatement的好处不只是防注入还有SQL预编译带来的性能提升以及代码可读性改善。更重要的是在Oracle中日期类型比较时直接用字符串拼接经常出现格式不匹配的诡异错误用setDate传参数则能稳定绕过这类问题。6. 常见问题与排查建议实际调试过程中几乎每个同学都会遇到几个经典报错这里整理一份排查速查表直接在遇到问题时对照报错现象常见原因解决办法ORA-12514: TNS listener does not currently know of service连接URL服务名写错或监听未启动检查URL中的服务名lsnrctl status查看监听状态ClassNotFoundException: oracle.jdbc.driver.OracleDriver驱动jar包未导入或导入路径错误把ojdbc8.jar放到lib目录并在构建路径中引入窗口中文全部显示为乱码方块JDK版本默认字体与中文不兼容为Swing组件统一设置支持中文的Font字体点击查询按钮界面卡死数据库查询在EDT线程中执行改用SwingWorker后台查询ORA-00911: invalid characterSQL语句末尾带了分号JDBC执行的SQL末尾不能加;删掉即可订票成功后余票没减少未把更新余票和插入订单放进同一事务用setAutoCommit(false)包住所有写操作排查上有个通用思路先看数据库本身能不能连上用SQL Developer或PL/SQL Developer先跑一遍要执行的SQL确认SQL没问题再回来看Java代码。很多时候问题根本不在Java而是SQL在Oracle中根本跑不通比如字段名大小写、NUMBER(10,2)插入数据超出精度等原因。写了这么多最后分享一点答辩和调试之外的实际经验做这种带数据库的项目测试数据一定要认真设计。别拿乱七八糟的测试数据入库后直接演示订票单号不连续、航班余票是负数、日期逻辑对不上都会被老师一眼看穿。我在指导学弟学妹时都会强调一个点ER图和流程图不是画完应付检查就完了它们是你写代码时的“施工图纸”。实际动手做的时候严格按照先设计表结构、再画流程图、最后写Swing代码的顺序走整个项目从启动到跑通比直接闷头写代码至少能省一半时间。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价