You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:48:55