JavaFX数据库新增条目窗口空指针异常问题求助
嘿,我来帮你一步步解决这个JavaFX+数据库的问题!从你的代码来看,主要有几个关键问题导致了NullPointerException和无法新增条目,咱们逐个来修复:
1. 先解决最直接的NullPointerException来源:mainApp未初始化
你在getPers方法里调用了((MainApp) this.mainApp).getDatabase(),但如果mainApp没有通过setMainApp方法被赋值,这里就会直接抛出空指针异常。必须确保在打开新增窗口时,给控制器传入mainApp实例,比如在MainApp中加载addPers的FXML时:
FXMLLoader loader = new FXMLLoader(getClass().getResource("../views/addPers.fxml")); AnchorPane pane = loader.load(); addPers controller = loader.getController(); controller.setMainApp(this); // 这一步绝对不能忘! controller.setDialogStage(dialogStage); // 同时设置对话框窗口
2. 修复setPers方法的空指针风险
如果是新增条目场景,你可能会给setPers传入null(因为没有已有的Pers对象),这时候pers.getName()就会炸。修改这个方法,兼容新增模式:
public void setPers(Pers pers) { this.pers = pers; if (pers != null) { // 编辑模式:填充已有数据 nameField.setText(pers.getName()); ageField.setText(Integer.toString(pers.getAge())); } else { // 新增模式:清空输入框 nameField.setText(""); ageField.setText(""); } }
3. 最关键的问题:新增条目的核心逻辑缺失
你现在的代码完全没有向数据库插入新数据的SQL语句!这就是为什么点击CreatePerson后数据库没反应的原因。咱们在CreatePerson方法里补上插入逻辑,还要完善输入验证:
@FXML public void CreatePerson(ActionEvent event) throws Exception{ Alert alert = new Alert(AlertType.ERROR); alert.setTitle("请检查输入"); alert.setHeaderText(null); // 先做输入验证,还要确保年龄是数字 String name = nameField.getText().trim(); String ageStr = ageField.getText().trim(); if(name.isEmpty()){ alert.setContentText("请输入有效的姓名"); alert.showAndWait(); return; // 验证失败直接返回,不执行后续逻辑 } int age; try { age = Integer.parseInt(ageStr); } catch (NumberFormatException e) { alert.setContentText("年龄必须是数字"); alert.showAndWait(); return; } // 核心:向数据库插入新条目 try { if (mainApp == null) { alert.setContentText("程序初始化失败,请重启"); alert.showAndWait(); return; } Database db = mainApp.getDatabase(); db.connect(); // 使用PreparedStatement防止SQL注入,比直接拼字符串安全 String insertQuery = "INSERT INTO PERSONS_DB (name, age) VALUES (?, ?)"; PreparedStatement stmt = db.getConnection().prepareStatement(insertQuery); stmt.setString(1, name); stmt.setInt(2, age); stmt.executeUpdate(); stmt.close(); // 插入成功提示 alert.setAlertType(AlertType.INFORMATION); alert.setContentText("条目创建成功!"); alert.showAndWait(); // 标记操作成功,关闭当前窗口 okClicked = true; dialogStage.close(); } catch (SQLException e) { alert.setContentText("插入失败:" + e.getMessage()); alert.showAndWait(); e.printStackTrace(); } }
4. 重构getPers方法,拆分职责
你的getPers方法现在既做数据库查询,又加载新窗口,职责混乱还会导致空指针(比如里面的page变量是null,new Scene(page)会炸)。咱们让它只负责查询数据库:
public ArrayList<Pers> getPers() throws SQLException { ArrayList<Pers> ListPers = new ArrayList<>(); // 注意SQL语句必须加SELECT关键字!你之前漏了 String query = "SELECT name, age FROM PERSONS_DB ORDER BY name;"; Database db = mainApp.getDatabase(); if (db == null) { throw new SQLException("数据库未初始化"); } try { db.connect(); ResultSet rslt = db.getResultOf(query); while (rslt.next()) { ListPers.add(new Pers(rslt.getString("name"), rslt.getInt("age"))); } rslt.close(); } finally { // 记得关闭数据库连接(如果你的Database类没有自动管理的话) if (db != null && db.isConnected()) { db.disconnect(); } } return ListPers; }
5. 优化场景切换逻辑
你原来在CreatePerson最后手动切换场景,很容易导致新的Database控制器没有被正确初始化。正确的做法是:
- 新增成功后关闭当前窗口
- 在MainApp中监听窗口关闭事件,然后刷新数据库列表UI
比如在MainApp中打开新增窗口的代码:
public void showAddPersDialog() { try { FXMLLoader loader = new FXMLLoader(getClass().getResource("../views/addPers.fxml")); AnchorPane page = loader.load(); Stage dialogStage = new Stage(); dialogStage.setTitle("新增条目"); dialogStage.initModality(Modality.WINDOW_MODAL); dialogStage.initOwner(primaryStage); Scene scene = new Scene(page); dialogStage.setScene(scene); addPers controller = loader.getController(); controller.setDialogStage(dialogStage); controller.setMainApp(this); controller.setPers(null); // 新增模式,传入null // 显示窗口,直到用户关闭 dialogStage.showAndWait(); // 如果用户成功新增,刷新数据库列表 if (controller.isOkClicked()) { refreshDatabaseList(); // 你需要在MainApp里实现这个方法,重新查询并更新UI } } catch (IOException e) { e.printStackTrace(); } }
最后,别忘了在addPers里给okClicked加个getter:
public boolean isOkClicked() { return okClicked; }
这样调整后,应该就能解决空指针问题,并且成功向数据库新增条目,同时刷新UI了!
内容的提问来源于stack exchange,提问作者vmicrobio
相关产品推荐
相关产品推荐

