Java获取GUI用户输入写入NetBeans Derby数据库失败排查
Derby数据库写入无记录问题修复方案
你的代码存在多处核心错误,直接导致数据无法落盘,逐个修正即可:
核心问题清单
- INSERT语句语法完全错误
你当前写的SQL有两个致命问题:- 用单引号包裹表名、列名:SQL中单引号是字符串常量的标记,不能用来包裹标识符(表名、列名),Derby会直接把
'PLAYERINFO'识别为字符串而非表名,报语法错误 - VALUES子句写死了
1,2,3,4,没有留?占位符:PreparedStatement的setXxx方法只会替换SQL里的?占位符,你写死常量的情况下,后续set参数的操作要么报参数数量不匹配错误,要么完全不生效
- 用单引号包裹表名、列名:SQL中单引号是字符串常量的标记,不能用来包裹标识符(表名、列名),Derby会直接把
- 操作的表名不匹配
你插入数据的目标表是PLAYERINFO,但调用表检查方法时传的参数是PLAYERS,相当于每次写入前检查/删除的是一张和业务无关的表,真正要写入的PLAYERINFO如果没提前创建,执行INSERT时会直接报表不存在的错误。 - 异常被静默吞掉
你的catch块只打印了ex.getMessage(),没有输出完整异常栈,Swing事件线程里的控制台输出很容易被忽略,SQL语法错、表不存在、主键冲突这些报错你根本看不到,表面上看就是点了按钮没反应、数据没写入。 - 事务未提交
如果你自定义的DBConnection类里关闭了自动提交(autoCommit=false),执行完executeUpdate()后必须手动调用conn.commit()才能把数据刷到磁盘,否则连接关闭时事务会自动回滚,数据不会持久化。 - 主键逻辑错误+危险的删表逻辑
playerID是方法内局部变量,每次调用方法都初始化为0,第一次插入ID是0,后续每次插入ID都是1,主键重复直接报错- 原来的表检查逻辑是找到同名表就直接删除,就算你前面的逻辑全对,每次跑程序都会把之前存的表删掉,永远看不到历史数据。
- 资源未正确释放
数据库连接、Statement、ResultSet都没有在执行完成后关闭,容易导致连接泄漏、事务锁不释放,后续写入操作直接阻塞。
修正后代码
1. 重写WritePlayerDB类
import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class WritePlayerDB { private final DBConnection dbc; private final Connection conn; // 静态变量维护自增ID,更推荐把PLAYER_ID设为数据库自增主键,避免应用端计数冲突 private static int playerID = 0; private static final String TARGET_TABLE = "PLAYERINFO"; public WritePlayerDB() throws SQLException { dbc = new DBConnection(); conn = dbc.getConnection(); // 调试阶段可以打开下面这行强制开启自动提交,避免忘记提交事务 // conn.setAutoCommit(true); } public void writeToPlayerDB() { // 正确的INSERT语句,用?做占位符,表名列名不用引号包裹 String insertQuery = "INSERT INTO " + TARGET_TABLE + " (PLAYER_ID, PLAYER_NAME, PRIZE_WON, CORRECT_ANSWERS) VALUES (?, ?, ?, ?)"; // 先校验目标表是否存在,不存在则建表 checkAndInitTable(TARGET_TABLE); // try-with-resources语法自动关闭Statement,不需要手动写close try (PreparedStatement ps = conn.prepareStatement(insertQuery)) { CorrectAnswers.correctAnswers[MillionaireGui.moneyCounter] = PrizeMoney.prizeLadder[MillionaireGui.moneyCounter]; ps.setInt(1, ++playerID); ps.setString(2, MillionaireGui.nameField.getText().trim()); ps.setInt(3, PrizeMoney.prizeLadder[MillionaireGui.moneyCounter]); ps.setInt(4, CorrectAnswers.correctAnswers[MillionaireGui.moneyCounter]); int affectedRows = ps.executeUpdate(); System.out.println("数据写入完成,影响行数:" + affectedRows); // 非自动提交模式下手动提交事务 if (!conn.getAutoCommit()) { conn.commit(); } } catch (SQLException ex) { // 打印完整异常栈,方便定位问题 ex.printStackTrace(); // 出错回滚事务 try { if (!conn.getAutoCommit()) conn.rollback(); } catch (SQLException rollbackEx) { rollbackEx.printStackTrace(); } } } // 原方法逻辑改成检查表是否存在,不存在则建表,禁止随便删表 private void checkAndInitTable(String tableName) { boolean tableExist = false; try (Statement stmt = conn.createStatement()) { DatabaseMetaData dbmd = conn.getMetaData(); // 直接查询目标表,不需要遍历全库表 ResultSet rs = dbmd.getTables(null, null, tableName.toUpperCase(), new String[]{"TABLE"}); if (rs.next()) { tableExist = true; } rs.close(); if (!tableExist) { String createSql = "CREATE TABLE " + tableName + " (" + "PLAYER_ID INT PRIMARY KEY, " + "PLAYER_NAME VARCHAR(100) NOT NULL, " + "PRIZE_WON INT, " + "CORRECT_ANSWERS INT)"; stmt.executeUpdate(createSql); System.out.println("表" + tableName + "初始化完成"); } } catch (SQLException ex) { ex.printStackTrace(); } } }
2. 修正GUI端调用逻辑
nameField.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { String inputName = nameField.getText().trim(); if (inputName.isEmpty()) { blankName.setVisible(true); blankName.setText("PLEASE DON'T LEAVE NAME BLANK"); return; } playerName.setPlayerName(inputName.toUpperCase()); try { WritePlayerDB wdb = new WritePlayerDB(); wdb.writeToPlayerDB(); blankNamePanel.setVisible(false); introRuleScreen(); } catch (SQLException ex) { blankName.setVisible(true); blankName.setText("数据保存失败,请查看控制台日志"); ex.printStackTrace(); } } });
额外排查提示
- 嵌入式Derby的数据库文件存在程序启动的工作目录下,如果你在NetBeans里切换了运行配置,可能连到了新的空数据库,要确认连接URL的路径和你查看数据的数据库路径一致
- 调试阶段不要关闭控制台的SQL日志输出,所有数据库报错都会打印在控制台,不要忽略这些信息
- 生产环境不要每次写入都新建数据库连接,建议把连接做成单例复用,避免连接泄漏
内容的提问来源于stack exchange,提问作者KhonsusKnight
相关产品推荐
相关产品推荐

