
简介这份实验报告面向高校计算机及相关专业学生聚焦《数据库应用程序开发》课程中Java与DB2交互的实操训练适合正在学习JDBC编程、需要完成课程实验或复习数据库应用开发基础的学习者参考。资源包共1个doc文档大小约1.76MB内容以实验报告形式组织涵盖JDBC连接建立、Statement与PreparedStatement使用、ResultSet结果集遍历、事务提交控制及SQL异常处理等核心知识点。报告按任务逐项记录调试过程与运行结果包括权限授予、对象名称修正、salary字段溢出原因分析、GUI改造与约束异常提示等典型问题的排查思路并配有截图说明。已有902人学习下载读者可借此对照实验步骤理解数据库与Java程序的交互流程掌握常见错误的定位与解决方法为后续数据库应用开发打下基础。1. 权限报错、未定义名称、事务不生效JDBC 连 DB2 的三个高频翻车点跑 JDBC 连 DB2 的实验最让人抓狂的不是写不出 SQL而是代码看着全对一运行就给你甩脸色要么db2admin没有访问EMPLOYEE的权限要么命令行一执行就报DB2ADMIN.TEMPL是一个未定义的名称要么更新语句返回成功、数据库里却纹丝不动。这三类问题几乎覆盖了数据库应用程序开发实验里八成以上的调试时间新手卡在第一条就动不了熟手也常被“成功但没生效”这种玄学现象绕进去。这篇笔记按报错现象、根因、可抄作业的解决步骤往下推适合正在做 JDBC 增删改查、被权限和事务坑住的开发者也适合想把排查路径固化下来的人。2. 权限与对象名报错为什么 db2admin 访问不了 EMPLOYEE2.1 报“没有访问 EMPLOYEE 的权限”时先查授权链这类报错通常出现在任务 1 补充程序片段之后程序能连上库但一执行查询就抛权限异常。根因不在 JDBC 代码而在 DB2 的用户授权模型EMPLOYEE表建在JLU用户模式下db2admin只是另一个用户默认没有任何跨模式的表访问权。很多人第一反应是改连接串里的用户名密码这没用因为问题出在库内的对象权限不是登录认证。常见做法是登录到拥有该表的用户把访问权显式授出去。命令行里执行-- 以 JLU 用户登录后执行把 EMPLOYEE 的查询权限授予 db2admin CONNECT TO sample USER JLU; GRANT SELECT ON JLU.EMPLOYEE TO USER db2admin; -- 如果程序还要做增删改按需补上对应权限 GRANT INSERT, UPDATE, DELETE ON JLU.EMPLOYEE TO USER db2admin;GRANT SELECT只给读权限实验里如果后续任务要改数据得把INSERT/UPDATE/DELETE一起授了否则会在下一个任务里再翻一次车。授权完成后重新用db2admin连接执行权限异常应当消失。这里的关键认知是JDBC 的getConnection成功只代表认证通过不代表你对目标表有操作权两者是两层校验。2.2 “DB2ADMIN.TEMPL 是一个未定义的名称”的两种来源这个报错在任务 1 和任务 5 都出现过但根因不完全一样得分开看。任务 1 里代码中写的是TEMPL而实际对象在JLU模式下DB2 在解析未加模式前缀的表名时会默认补上当前连接用户的模式于是拼成了DB2ADMIN.TEMPL自然找不到。解决办法是把代码里的表名改成带模式的全名JLU.TEMPL让解析不再依赖默认模式。任务 5 更隐蔽想创建JLU.TEMPL表却创建不了报的是对象已存在或名称冲突。根因是之前给EMPLOYEE建过别名TEMPL别名和表在同一个命名空间里抢名字。处理方式是先删掉旧别名再建表-- 先确认当前模式下有哪些别名和表在抢 TEMPL 这个名字 SELECT NAME, TYPE FROM SYSIBM.SYSTABLES WHERE NAME TEMPL; -- 删除遗留别名后再创建表 DROP ALIAS JLU.TEMPL; CREATE TABLE JLU.TEMPL ( ... );SYSIBM.SYSTABLES里TYPE字段能区分是表还是别名先查再删避免误删真实表。这类“名称未定义”看着像代码 bug实际是模式解析和命名空间冲突排查顺序应该是先确认对象真实全名再确认当前连接用户的默认模式最后才怀疑代码拼写。3. 更新成功却不生效事务提交与溢出报错怎么定位3.1 setAutoCommit(false) 之后忘了 commit 的典型症状任务 3 里最迷惑的现象是输入 20 或 30程序执行成功executeUpdate也返回了影响行数但去 DB2 里查数据一点没变。很多人会怀疑 SQL 写错、怀疑表被锁甚至在 DB2 命令行里手动改一遍验证“库本身能改”结果证明库没问题问题在 Java 程序。根因就是sample.setAutoCommit(false)把自动提交关了后续所有更新都挂在一个未提交的事务里连接一关就回滚了。解决方式有两种按实验要求选。如果就是要练手动事务那必须在更新后显式提交// 关闭自动提交手动控制事务边界 sample.setAutoCommit(false); try { int updateCount pstmt.executeUpdate(); sample.commit(); // 关键不 commit 数据不会落库 System.out.println(影响行数: updateCount); } catch (SQLException x) { sample.rollback(); // 出错回滚避免半截事务 System.out.println(SQLCode x.getErrorCode() SQLState x.getSQLState() Message x.getMessage()); }commit()是让改动真正写进库的动作rollback()是出错时的后悔药。如果实验不要求手动事务直接把setAutoCommit(false)改成true也能让更新立即生效但这样就失去了事务控制的练习意义。我一般会保留false并补上commit因为真实业务里批量更新几乎都要手动控制边界。3.2 类型转换溢出为什么输入 15 和 20 会炸、16 却“改 0 行”溢出报错的表现是类型转换时数值超出字段范围。实验里通过改 SQL 因子做了对照salary*2时 15 和 20 都溢出salary*1.01时都不溢出这就把根因锁定在“修改后的数值超过了salary字段能容纳的范围”而不是代码类型声明写错。定位手法很直接先用 DB2 查出相关行的原始salary手算放大后的值再对照字段定义看上限。-- 查字段类型和精度确认能装多大 SELECT COLNAME, TYPENAME, LENGTH, SCALE FROM SYSIBM.SYSCOLUMNS WHERE TBNAME STAFF AND COLNAME SALARY; -- 查目标行的原始值手算放大结果 SELECT ID, NAME, SALARY FROM JLU.STAFF WHERE DEPT 20;LENGTH和SCALE决定了数值上限放大后的值一旦越界就会在executeUpdate时抛溢出。另一个容易混淆的点是“输入 16 反馈修改了 0 行”这不是溢出是数据库里根本没有对应记录executeUpdate返回 0 是正常语义。把“返回 0 行”和“抛溢出异常”分开看能少走很多弯路。4. GUI 改造与异常处理JOptionPane 和约束报错怎么接住4.1 用 JOptionPane 做输入输出时的空值与类型坑任务 4 要求把labupdate.java改成 GUI 形式输入和结果都走JOptionPane。这里最常见的翻车是JOptionPane.showInputDialog返回的是字符串直接拿去setInt会抛类型不匹配用户点取消返回null不判空就parseInt会直接空指针。稳妥写法是先判空再转换转换失败给提示而不是让异常冒到控制台String input JOptionPane.showInputDialog(请输入部门号:); if (input null || input.trim().isEmpty()) { JOptionPane.showMessageDialog(null, 输入不能为空); return; } int mydeptno; try { mydeptno Integer.parseInt(input.trim()); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(null, 请输入合法数字); return; } pstmt.setInt(1, mydeptno);trim()是为了挡掉用户手滑打出的空格NumberFormatException捕获的是非数字输入。GUI 改造本身不难难在把控制台时代的“报错看堆栈”换成“报错弹对话框”所有用户输入路径都得当成不可信数据处理。4.2 任务 7 的异常分类约束、类型、溢出、非法符号各归各的任务 7 要求用对话框提示所有操纵类错误实验里列了四类违反约束、类型不匹配、溢出、SQL 语句非法符号。这四类在SQLException里靠getErrorCode()和getSQLState()区分统一 catch 之后按错误码分流提示比每个操作各写一套 try-catch 更好维护try { int n pstmt.executeUpdate(); JOptionPane.showMessageDialog(null, 影响行数: n); } catch (SQLException x) { String msg; switch (x.getErrorCode()) { case -803: msg 违反唯一约束; break; // 具体码以实际库为准 case -545: msg 数值超出字段范围; break; default: msg SQLState x.getSQLState() 信息 x.getMessage(); } JOptionPane.showMessageDialog(null, msg); }错误码的具体数值要以实际 DB2 版本返回为准实验里更稳的做法是先把getErrorCode、getSQLState、getMessage三个值原样弹出来跑一遍四类错误各记一次再回头写分流逻辑。这样既完成了异常处理要求也顺手把错误码对照表建起来了。5. 避坑清单五个反复踩到的 JDBC 实验坑5.1 坑一连接成功就以为有表权限现象是程序连库正常一查表就报权限异常。原因是认证和对象授权是两层db2admin登录成功不代表对JLU模式下的表有访问权。解决是按 2.1 的GRANT语句补授权并且把后续任务需要的增删改权限一次授全别等下一个任务再回来补。5.2 坑二表名不带模式前缀现象是报DB2ADMIN.XXX 未定义。原因是未加前缀的表名会被补上当前用户模式和实际对象所在模式对不上。解决是代码里统一写全名JLU.表名或者在连接后执行SET SCHEMA JLU把默认模式切过去二选一别混着用。5.3 坑三别名和表抢名字现象是建表失败提示名称冲突。原因是之前给别的表建过同名别名别名和表共享命名空间。解决是先查SYSIBM.SYSTABLES确认TYPE删掉遗留别名再建表删之前务必确认不是真实表。5.4 坑四关了自动提交不 commit现象是更新返回成功但库里没变。原因是setAutoCommit(false)后事务未提交连接关闭即回滚。解决是补commit()出错走rollback()别只改true了事那样事务练习就白做了。5.5 坑五把“改 0 行”当成溢出现象是输入某个部门号后提示修改 0 行误以为是数值问题。原因是该部门在表里没有记录executeUpdate返回 0 是正常结果。解决是先SELECT确认记录存在再区分“0 行”和“抛溢出异常”两种完全不同的反馈。6. 快速定位这类问题的排查顺序与验证手法被 JDBC 报错卡住时我一般按“连接层 → 对象层 → 语句层 → 事务层”四步往下压每步都有明确的验证动作不靠猜。连接层先确认getConnection用的 URL、用户、密码和实际库一致能连上就进下一步对象层用SYSIBM.SYSTABLES和SYSIBM.SYSCOLUMNS查对象真实全名、类型和字段精度把“名称未定义”和“溢出上限”这两类问题在这一层摁掉语句层把拼好的 SQL 拿到 DB2 命令行里裸跑一遍能跑通说明问题在 Java 参数绑定跑不通说明 SQL 本身有问题事务层最后查getAutoCommit状态和有没有commit专治“成功但不生效”。报错关键词优先怀疑层验证动作没有访问 XXX 的权限对象层查授权补 GRANTXXX 是一个未定义的名称对象层查全名与默认模式确认别名冲突类型转换溢出对象层查字段 LENGTH/SCALE手算放大值执行成功但数据没变事务层查 autoCommit补 commit修改 0 行语句层先 SELECT 确认记录存在验证手法上我习惯在 catch 里把getErrorCode、getSQLState、getMessage三个值一次性打全或弹全别只打一句“出错了”。这三个值分别对应库内错误码、标准状态码和人类可读信息定位时缺一个都可能多绕半小时。GUI 任务里也一样异常对话框先把原始三值展示出来再谈友好提示顺序反了就会把根因藏起来。从那以后我每次写 JDBC 更新逻辑都强制走一遍“先 SELECT 验证记录、再确认 autoCommit、最后 commit 并回查”的固定动作权限和模式前缀也在建连接后第一时间确认不再等报错来提醒。希望这套顺序能帮到你少在同一个坑里翻两次车。本文还有配套的精品资源点击获取