java.sql.SQLException: 没有为参数 5.update database 指定值

java.sql.SQLException: No value specified for parameter 5. update database

当我尝试将我的 JTable/JTextFields 更新到我的 SQL 数据库时,对话框中有这个错误代码:java.sql.SQLException: No value specified for parameter 5

我在网站上查看过类似的问题,但似乎没有解决我的问题的方法。我已经检查了数据库,我已经检查了我的连接代码、更新代码,但找不到导致问题的这个额外参数应该在哪里?请帮助新手!

所以现在我明白问题出在 WHERE id=? 正如我所怀疑的那样,但我的 ID 仅作为行 count/main 键存在于我的 SQL 数据库中,所以它会根据您 choose/click 所在的行而有所不同,因此我无法预先在 pst.setInt(5, ? ) 处设置特定值。那么应该插入什么 - 这样我就不会丢失 JTable 中我的客户列表中的自动行数?

//This method contains all codes for database connection.
    private void upDateDB() {
    try { 
    Class.forName("com.mysql.cj.jdbc.Driver");
    Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/num klienter", "root", "");
    PreparedStatement pst = con.prepareStatement("SELECT * FROM klient");
        
    ResultSet rs =pst.executeQuery();
    ResultSetMetaData StData = rs.getMetaData();
        
    q = StData.getColumnCount();
        
    DefaultTableModel RecordTable = (DefaultTableModel)table.getModel();
    RecordTable.setRowCount(0);
        
    while(rs.next()){
       Vector<String> columnData = new Vector<String>();
            
    for (i = 1; i <= q; i++) {
       columnData.add(rs.getString("id"));
       columnData.add(rs.getString("Name"));
       columnData.add(rs.getString("Birthday"));
       columnData.add(rs.getString("Description"));
       columnData.add(rs.getString("Other"));
}
       RecordTable.addRow(columnData);                
            
 }} catch (Exception ex) {
       JOptionPane.showMessageDialog(null, ex);
}}

updateButton.addActionListener(new ActionListener() {
        public void actionPerformed (ActionEvent arg0) { 
            
        try { 
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection con = DriverManager.getConnection("jdbc:mysql://localhost/num klienter", "root", "");    
            PreparedStatement pst = con.prepareStatement("UPDATE klient SET Name=?,Birthday=?,Description=?,Other=? WHERE id=?");
            table.getSelectedRow();
        
            pst.setString(1, nameTxt.getText()); 
            pst.setString(2, dayTxt.getText()+"-" + monthTxt.getText()+"-" + yearTxt.getText());
            pst.setString(3, descriptionTxt.getText());
            pst.setString(4, otherTxt.getText());
            pst.executeUpdate();
            
            JOptionPane.showMessageDialog(null, "Updated in database");
            upDateDB();
            
        }catch (Exception ex){
            JOptionPane.showMessageDialog(null, ex); 
}

Class.forName("com.mysql.cj.jdbc.Driver");

这可以删除。 20 年来一直没有必要。

Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/num klienter", "root", "");

这是内存泄漏;连接已打开,并将永远保持打开状态;您的 SQL 服务器不允许打开的连接超过少数,所以很快您的 MySQL 服务器将无法通过任何服务(包括此 java 代码)访问,直到您杀死 java 关闭连接的应用程序。将 try with resources 用于您创建的 所有 资源。

PreparedStatement pst = con.prepareStatement("SELECT * FROM klient");

这也是一个资源,需要尝试使用资源。

ResultSet rs =pst.executeQuery();

你猜对了。第三次尝试使用资源。如果您发现代码变得笨拙,JDBC 是非常低级的,对于 'end user' 编码来说并不是那么好。使用像 JDBI or JOOQ.

这样的抽象概念

columnData.add(rs.getString("Fødselsdag"));

您的列名称中是否包含非 ASCII?那永远不会顺利。我强烈建议你不要这样做。

q = StData.getColumnCount();

for (i = 1; i <= q; i++) {

这很奇怪。 q 包含 column count - 这是查询中的列数。然后你硬编码 5 个列名,所以 q 总是 5。然后,你添加所有 5 个值(id、Navn、Fødselsdag 等),然后这样做 5 次,总共运行 25 次,并重复你的数据5次。目前尚不清楚您试图通过询问已知信息(从您已经知道的元数据中获取列数)来完成什么。

PreparedStatement pst = con.prepareStatement("UPDATE klient SET Navn=?,Fødselsdag=?,Beskrivelse=?,Andet=? WHERE id=?");

我数了 5 个 ?,但只有 4 个 pst.setString 语句。你忘了 pst.setInt(5, theValue).

更新代码获得了关于 try-with-resources 的所有相同警告。

pst.setString(2, dayTxt.getText()+"-" + monthTxt.getText()+"-" + yearTxt.getText());

不是你如何与 DB 约会。有一个 pst.setDate,但最好你应该使用 pst.setObject,传递一个 java.time.LocalDate 的实例。 MySQL 是否真的支持 - 不确定,你必须检查一下。

我的问题的解决方案是像这样为 id=? 插入第 5 个 pst. 语句:

pst.setInt(5,table.getRowCount());