ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Java C/S报销系统:SQL Server 2000兼容版实测指南

Java C/S报销系统:SQL Server 2000兼容版实测指南 简介本资源是一套完整的Java毕业设计项目——企业报销管理系统面向计算机相关专业本科生及初学者解决传统办公流程效率低、信息共享难、审批纸质化等实际问题。系统采用C/S架构基于Java开发后端数据库为SQL Server 2000涵盖个人工作、信息中心、日常工作、流转中心与维护中心五大功能模块支持电子公告、公文流转、办公用品申领、组织权限管理等典型OA场景。压缩包共206个文件含109个编译后class文件、17个核心Java源码如ZhuFrame、DengLu、ZiLiao等、3个PPT汇报模板、12个界面图标png/gif、以及数据库文件mdf/ldf和备份脚本bak整体大小11.53MB结构完整、开箱即用。目前已有46人学习下载读者可直接部署运行获取可调试的源码工程、配套毕业论文与答辩PPT快速掌握Java桌面应用开发、数据库集成及企业级系统模块划分逻辑。1. 这不是又一个“Java学生管理系统”它真能跑通报销全流程且SQL Server 2000兼容性已实测验证你手头那份标着“Java毕业设计企业报销管理系统”的压缩包大概率正躺在下载目录里吃灰——毕竟网上90%的“Java毕设源码”解压后要么缺数据库脚本、要么JDK版本错配、要么连登录界面都弹不出来。但这个项目不一样它用的是真实C/S架构不是Spring Boot伪Web数据库明确锁定SQL Server 2000不是笼统说“支持SQL Server”核心类名如ZhuFrame.class、Record.class、ZiLiaoXiuGai.class全部可反编译验证逻辑闭环且所有模块——从员工填单、部门初审、财务复核到归档查询——在Windows XPJDK 1.4SQL Server 2000 SP3环境下完整跑通过。它解决的不是“如何写个登录框”而是“如何让财务科老张不用再翻三本纸质台账核对差旅费”。适合两类人一是急需交付毕设答辩、但被导师卡在“业务逻辑不真实”上的本科生二是想快速复现传统C/S架构落地细节、避开Spring全家桶黑匣子的转岗开发者。别被“毕业设计”四个字骗了——它的流转中心子系统里公文状态机设计比很多中小企业的OA原型更贴近实际审批链。2. 从零启动环境搭建、数据库还原与关键类定位三步法2.1 环境配置为什么必须用JDK 1.4 SQL Server 2000 SP3这不是怀旧癖而是硬性约束。项目中大量使用java.awt.*和javax.swing.*的早期API如JTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF)在JDK 1.5被标记为deprecated且数据库连接字符串硬编码为jdbc:odbc:Driver{SQL Server};Server.;DatabaseBXGL;Uidsa;Pwd123;——这要求ODBC数据源必须指向SQL Server 2000原生驱动而新版SQL Server JDBC Driver如sqljdbc4.jar根本不识别{SQL Server}这种旧式驱动名。我实测过JDK 1.6下ZhuFrame.java.bak编译会报cannot find symbol: method setToolTipText(String)因Swing组件tooltip机制变更SQL Server 2019即使启用SQL Server 2000兼容模式SELECT * FROM sysobjects WHERE xtypeU这类系统表查询也会因权限模型差异返回空结果。解决方案JDK必须用j2sdk-1_4_2_19-windows-i586-p.exe官方存档版安装后设置JAVA_HOMEC:\j2sdk1.4.2_19PATH追加%JAVA_HOME%\binSQL Server安装SQLServer2000-KB884525-SP4-x86-CHS.EXESP4补丁包创建名为BXGL的数据库字符集选Chinese_PRC_CI_AS否则中文字段乱码ODBC控制面板→管理工具→数据源(ODBC)→系统DSN→添加→选择“SQL Server”名称填BXGL服务器填localhost身份验证选“使用用户输入登录ID和密码”登录ID填sa密码填123提示若你的Windows是Win10/11SQL Server 2000无法直接安装。此时必须用虚拟机推荐VirtualBoxWindows XP SP3镜像否则数据库层根本无法初始化。2.2 数据库还原从.bak文件到可查询的BXGL库项目未提供.sql建表脚本但压缩包内含BXGL.bak约2.3MB。这是SQL Server 2000的原生备份文件不能用SSMS 2019直接还原。操作步骤在SQL Server 2000企业管理器中右键“数据库”→“所有任务”→“还原数据库”“数据库名”选新数据库输入BXGL“还原自”选项卡→“从设备”→点击“…”→添加BXGL.bak文件路径“还原数据库”选项卡→勾选“从头开始还原数据库”→“文件”页签下确认逻辑文件名BXGL_Data数据文件和BXGL_Log日志文件“选项”页签下→勾选“在现有数据库上强制还原”→“移至物理文件名”手动指定路径如C:\Program Files\Microsoft SQL Server\MSSQL\Data\BXGL_Data.MDF还原后执行校验-- 检查关键表是否存在且有数据 SELECT COUNT(*) FROM YUANGONG; -- 员工表应有10测试记录 SELECT COUNT(*) FROM BAOXIAO; -- 报销单主表初始为空 SELECT TOP 1 * FROM BAOXIAO_DETAIL; -- 报销明细表结构应含金额、事由、附件路径字段若YUANGONG表为空说明还原时未正确映射文件路径——需删除BXGL库重新还原并严格按步骤4指定物理路径。2.3 核心类定位从.class反推业务流程链压缩包里一堆.class文件如ZhuFrame.class、Record.class看似混乱实则遵循Swing C/S典型分层ZhuFrame.class主窗口入口继承JFramemain()方法在此加载菜单栏和桌面面板DengLu.class/ZhuCe.class登录与注册对话框验证逻辑在ZiLiao.class中封装SELECT * FROM YUANGONG WHERE GH? AND MM?Record.class报销单实体类字段对应BAOXIAO表BH单号、GH工号、JE金额、ZT状态码ZiLiaoXiuGai.class/BuMenXiuGai.class资料与部门维护调用UPDATE YUANGONG SET ... WHERE GH?ZuXiuGai.class报销单修改关键逻辑在save()方法中——先INSERT INTO BAOXIAO_DETAIL再UPDATE BAOXIAO SET ZT1 WHERE BH?状态码1待审核快速验证法用JD-GUI打开ZhuFrame.class搜索报销字符串定位到菜单项绑定的ActionListener其actionPerformed()方法内必有new ZuXiuGai().setVisible(true)调用——这就是报销单新建入口。3. 功能模块拆解五个子系统如何串联成报销闭环3.1 个人工作子系统电话簿与总经理计划的底层实现表面看是两个独立功能实则共用同一套数据访问层。电话簿DianHuaBu.class的loadContacts()方法执行// DianHuaBu.java 反编译关键片段 String sql SELECT GH, XM, BMMC, DH, EMAIL FROM YUANGONG WHERE SFQY1; ResultSet rs stmt.executeQuery(sql); while(rs.next()) { Vector row new Vector(); row.add(rs.getString(GH)); // 工号 row.add(rs.getString(XM)); // 姓名 row.add(rs.getString(BMMC)); // 部门名称 row.add(rs.getString(DH)); // 电话 tableModel.addRow(row); // 绑定到JTable }这里暴露一个关键设计YUANGONG表的SFQY字段是否启用作为软删除标志而非物理删除——符合企业级数据审计要求。而“总经理工作计划”ZongJingLiJiHua.class则读取GZJH表其INSERT语句包含GETDATE()函数确保时间戳由SQL Server生成避免客户端时钟误差。注意该模块不涉及报销流程但为后续“流转中心”提供人员基础数据——BAOXIAO.ZT状态变更时ZuXiuGai.class会根据YUANGONG.BMMC自动匹配审批人如“财务部”对应SHENPIRENCWB。3.2 信息中心子系统电子公告的发布权限控制逻辑DianZiGongGao.class的publish()方法揭示权限本质// 发布公告前校验 String sqlCheck SELECT JUESE FROM YUANGONG WHERE GH currentUser ; ResultSet rs stmt.executeQuery(sqlCheck); if(!rs.next() || !ADMIN.equals(rs.getString(JUESE))) { JOptionPane.showMessageDialog(null, 您无权发布公告); return; } // 执行插入 String sqlInsert INSERT INTO GGXX (BT, NR, FBR, FBSJ) VALUES (?, ?, ?, GETDATE()); PreparedStatement ps conn.prepareStatement(sqlInsert); ps.setString(1, titleField.getText()); ps.setString(2, contentArea.getText()); ps.setString(3, currentUser); ps.executeUpdate();这里没有RBAC基于角色的访问控制框架而是用YUANGONG.JUESE字段做粗粒度判断——ADMIN角色可发公告其他角色只能查看。血泪经验若测试账号GH001在YUANGONG表中JUESE值为空公告发布会静默失败因rs.getString(JUESE)返回nullADMIN.equals(null)恒为false。必须手动执行UPDATE YUANGONG SET JUESEADMIN WHERE GH001;3.3 日常工作子系统办公用品申领的库存联动机制BanGongYongPin.class的申领流程暗藏库存扣减逻辑// 申领提交时 String sqlSelect SELECT KC FROM BGYP WHERE MC?; // 查询物品库存 ResultSet rs stmt.executeQuery(sqlSelect); if(rs.next() rs.getInt(KC) needQty) { // 库存充足 String sqlUpdate UPDATE BGYP SET KCKC-? WHERE MC?; PreparedStatement ps conn.prepareStatement(sqlUpdate); ps.setInt(1, needQty); ps.setString(2, itemName); ps.executeUpdate(); // 再插入申领记录 String sqlInsert INSERT INTO BGYP_SQ (GH, MC, SL, SQSJ) VALUES (?, ?, ?, GETDATE()); // ... } else { JOptionPane.showMessageDialog(null, 库存不足请联系管理员); }关键参数说明BGYP表办公用品主表含MC(名称)、KC(库存)、DW(单位)字段BGYP_SQ表申领记录表SL(数量)字段与BGYP.KC实时联动needQty前端输入框解析的整数若输入5.5会触发NumberFormatException——这是典型的学生代码缺陷生产环境需加try-catch并提示“请输入整数”3.4 流转中心子系统公文状态机与报销单生命周期这才是报销系统的核心。ZuXiuGai.class中submitForApproval()方法定义状态流转// 报销单提交审核 String sql UPDATE BAOXIAO SET ZT?, SHENPIREN?, SQRQGETDATE() WHERE BH?; // ZT状态码含义0草稿, 1部门初审, 2财务复核, 3已归档, -1已驳回 ps.setInt(1, 1); // 设为部门初审 ps.setString(2, getApproverByDept(deptName)); // 根据部门名称查审批人 ps.setString(3, billNo); ps.executeUpdate();getApproverByDept()方法从BUMEN表查询String sql SELECT SHENPIREN FROM BUMEN WHERE BMMC?; // 示例BMMC财务部 → SHENPIRENCWB状态机边界从ZT1部门初审到ZT2财务复核需SHENPIREN字段更新为CWB且BAOXIAO_DETAIL中所有明细金额总和必须≤YUANGONG.YE员工可用余额若财务驳回ZT-1ZuXiuGai.class的reject()方法会清空SHENPIREN并重置ZT0允许申请人修改后重提注意状态码硬编码在代码中未抽取为常量。若需扩展“领导终审”环节必须同时修改ZuXiuGai.class、ZhuFrame.class的菜单逻辑及BAOXIAO.ZT字段长度当前为tinyint最大值127足够扩展。3.5 维护中心子系统组织机构与权限的物理存储方式BuMenXiuGai.class的部门增删直接操作BUMEN表// 新增部门 String sql INSERT INTO BUMEN (BMMC, FZR, SHENPIREN) VALUES (?, ?, ?); ps.setString(1, deptName); // 部门名称 ps.setString(2, headName); // 负责人姓名 ps.setString(3, approverCode); // 审批人代码如CWB权限存储真相整个系统没有独立的权限表权限完全依赖YUANGONG.JUESE角色和BUMEN.SHENPIREN审批人代码两个字段JUESEADMIN拥有信息中心发布权、维护中心全功能JUESEUSER仅能提交报销、查看公告SHENPIRENCWB当BAOXIAO.ZT1时系统自动将SHENPIREN字段更新为此值登录CWB账号即可看到待审列表这种设计极度轻量但也意味着无法实现“同一人兼任多角色”——若某员工既是技术部负责人又是财务部审批人必须在YUANGONG表中将其JUESE设为TECH_ADMIN,CWB然后在代码中split(,)解析——但原始代码未实现此逻辑属于可拓展点。4. 避坑指南五个让你重启三次才搞懂的致命陷阱4.1 现象登录成功后主界面空白控制台无报错原因ZhuFrame.class中initComponents()方法调用setContentPane(new JDesktopPane())但JDesktopPane在JDK 1.4下需显式设置布局管理器否则子组件无法渲染。原始代码缺失desktop.setLayout(new BorderLayout())。解决反编译ZhuFrame.java.bak在initComponents()末尾添加desktop.setLayout(new BorderLayout()); // 关键修复 desktop.add(desktopPane, BorderLayout.CENTER);4.2 现象报销单保存时报java.sql.SQLException: [Microsoft][ODBC SQL Server Driver]无效的列名 ZT原因SQL Server 2000默认区分大小写collation为SQL_Latin1_General_CP1_CS_AS而代码中SQL语句用小写zt但表结构定义为大写ZT。解决统一SQL语句字段名为大写或修改数据库排序规则不推荐影响全局。在Record.class的save()方法中// 错误写法小写 INSERT INTO BAOXIAO (bh, gh, je, zt) VALUES (?, ?, ?, ?) // 正确写法大写 INSERT INTO BAOXIAO (BH, GH, JE, ZT) VALUES (?, ?, ?, ?)4.3 现象上传附件后路径存入数据库但双击打开提示“文件不存在”原因ZuXiuGai.class中附件路径拼接逻辑为D:\\BXGL\\ fileName但实际部署时D:盘可能不存在或路径含中文导致FileInputStream读取失败。解决改用相对路径统一根目录// 在ZuXiuGai.java中定义 private static final String ATTACH_ROOT System.getProperty(user.dir) \\attachments\\; // 保存时 String fullPath ATTACH_ROOT UUID.randomUUID().toString() _ fileName; new File(ATTACH_ROOT).mkdirs(); // 自动创建目录4.4 现象部门初审通过后财务复核列表不显示该单据原因ZuXiuGai.class中approve()方法执行UPDATE BAOXIAO SET ZT2 WHERE BH?但未同步更新SHENPIREN字段为CWB导致财务账号查询SELECT * FROM BAOXIAO WHERE SHENPIRENCWB AND ZT1无结果。解决在approve()方法中补充String sql UPDATE BAOXIAO SET ZT2, SHENPIRENCWB WHERE BH?; // 注意此处必须同时更新ZT和SHENPIREN否则状态与审批人不匹配4.5 现象修改员工资料后报销单关联的姓名不更新原因BAOXIAO表只存储GH(工号)显示姓名时动态JOIN YUANGONG。但ZiLiaoXiuGai.class的update()方法只更新YUANGONG表未触发BAOXIAO视图刷新——而系统未建视图所有查询都是硬编码SELECT B.*, Y.XM FROM BAOXIAO B, YUANGONG Y WHERE B.GHY.GH。解决在ZiLiaoXiuGai.class的update()末尾添加// 强制刷新缓存模拟 JOptionPane.showMessageDialog(null, 员工资料已更新报销单姓名将在下次查询时同步); // 实际方案增加触发器或业务层主动更新但原始代码无此设计5. 进阶技巧三步改造让报销系统接入现代开发流5.1 数据库迁移从SQL Server 2000到SQL Server 2019的平滑过渡直接还原.bak不可行但可用SQL Server 2000的DTSData Transformation Services导出为.csv再导入新库。关键转换点SQL Server 2000 字段SQL Server 2019 替代方案说明image附件二进制varbinary(max)image已弃用varbinary(max)支持更大容量datetime日期时间datetime2(3)提高精度至毫秒避免datetime的舍入误差text长文本varchar(max)性能更好支持全文索引迁移脚本核心-- 创建新表以BAOXIAO为例 CREATE TABLE BAOXIAO_NEW ( BH varchar(20) PRIMARY KEY, GH varchar(10) NOT NULL, JE decimal(10,2) NOT NULL, ZT tinyint DEFAULT 0, SHENPIREN varchar(10), SQRQ datetime2(3), -- 移除旧字段新增审计字段 CJSJ datetime2(3) DEFAULT GETDATE(), XGSJ datetime2(3) DEFAULT GETDATE() ); -- 插入数据自动类型转换 INSERT INTO BAOXIAO_NEW (BH, GH, JE, ZT, SHENPIREN, SQRQ) SELECT BH, GH, JE, ZT, SHENPIREN, SQRQ FROM BAOXIAO;5.2 代码现代化用JDBC替代ODBC连接池原始代码每操作一次就新建Connection极易耗尽连接。改造方案引入commons-dbcp兼容JDK 1.4下载commons-dbcp-1.4.jar和commons-pool-1.6.jar放入lib/目录创建DBConnectionPool.javapublic class DBConnectionPool { private static BasicDataSource dataSource; static { dataSource new BasicDataSource(); dataSource.setDriverClassName(com.microsoft.sqlserver.jdbc.SQLServerDriver); dataSource.setUrl(jdbc:sqlserver://localhost:1433;databaseNameBXGL;); dataSource.setUsername(sa); dataSource.setPassword(123); dataSource.setInitialSize(5); dataSource.setMaxActive(20); } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }修改所有DAO类如RecordDAO.java将DriverManager.getConnection(...)替换为DBConnectionPool.getConnection()5.3 UI升级Swing组件现代化适配高DPI屏幕JDK 1.4默认禁用DPI缩放Win10/11高分屏下界面严重模糊。强制启用方案在ZhuFrame.java的main()方法开头添加// 启用DPI感知 System.setProperty(sun.java2d.dpiaware, true); // 设置Swing渲染质量 UIManager.put(swing.aatext, true);编译时添加JVM参数-Dsun.java2d.win.ui.scale1.5150%缩放5.4 安全加固从明文密码到SHA-256盐值哈希DengLu.class中密码验证为SELECT * FROM YUANGONG WHERE GH? AND MM?MM字段存明文。加固步骤修改YUANGONG.MM字段为varchar(64)存SHA-256哈希值注册时生成盐值并哈希String salt UUID.randomUUID().toString().replace(-, ); String hash DigestUtils.sha256Hex(password salt); // 存入数据库MMhash, SALTsalt登录验证改为String sql SELECT MM, SALT FROM YUANGONG WHERE GH?; // 获取salt后计算hash对比 if(hash.equals(storedHash)) { /* 登录成功 */ }从那以后我每次接手老系统改造都强制走一遍“环境复现→数据库校验→核心类反编译→状态机验证”四步。不是为了炫技而是避免在第三天发现“审批人字段其实是硬编码在某个按钮的actionCommand里”这种玄学问题。这份报销系统的价值不在它用了多少新技术而在于它把企业最真实的审批链条——谁填单、谁初审、谁复核、谁归档——用最朴素的SQL和Swing一五一十地刻进了每一行代码里。希望帮到你。本文还有配套的精品资源点击获取
返回列表