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

通过JTable更新MySQL数据库时遇参数索引越界SQL异常

JTable编辑MySQL数据同步更新报错解决方案

用户遇到的错误:

java.sql.SQLException: Parameter index out of range (0 < 1 )

需求是实现JTable展示并编辑MySQL数据,点击更新按钮将修改同步到数据库,但当前代码触发上述错误,尝试多种UPDATE语句均无效。相关代码如下:

主类代码

public class Main{
    public static void main(String[] args) {
        new MyFrame();
    }
}

主菜单类代码

package com.company;

import javax.swing.*;
import java.awt.*;

public class MyFrame extends JFrame{

    JLabel label;
    JMenu Add;
    JMenu remove;
    JMenu items;
    JMenu vendors;
    JMenuBar menuBar;
    JMenuItem addCustomer;
    JMenuItem addVendors;
    JMenuItem addProducts;
    JMenuItem removeCustomer;
    JMenuItem removeProduct;
    JMenuItem removeVendor;

    MyFrame(){
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLayout(new FlowLayout());

        label = new JLabel("Inventory Software");
        label.setFont(new Font("Comic Sans MS", Font.BOLD, 30));

        menuBar = new JMenuBar();

        Add = new JMenu("Add");
        remove = new JMenu("Edit");
        items = new JMenu("Items");
        vendors = new JMenu("Vendors");

        addCustomer = new JMenuItem("Add Customers");
        addVendors = new JMenuItem("Add Vendors");
        addProducts = new JMenuItem("Add Products");

        removeCustomer = new JMenuItem("Edit Customer");
        removeProduct = new JMenuItem("Edit Product");
        removeVendor = new JMenuItem("Edit Vendor");

        remove.add(removeCustomer);
        remove.add(removeProduct);
        remove.add(removeVendor);

        Add.add(addCustomer);
        Add.add(addProducts);
        Add.add(addVendors);

        menuBar.add(Add);
        menuBar.add(remove);
        menuBar.add(items);
        menuBar.add(vendors);

        addCustomer.addActionListener(new WindowAC());
        addVendors.addActionListener(new WindowAV());
        addProducts.addActionListener(new WindowAP());
        removeCustomer.addActionListener(new WindowRC());
        removeVendor.addActionListener(new WindowRV());
        removeProduct.addActionListener(new WindowRP());

        this.setPreferredSize(new Dimension(550, 300));
        this.setJMenuBar(menuBar);
        this.add(label);
        this.pack();
        this.setVisible(true);
        this.getContentPane().setBackground(Color.WHITE);
        this.setLocationRelativeTo(null);
        this.setTitle("Intact Communications Inventory Software");
    }
}

编辑客户并更新数据库的原错误代码

package com.company;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.*;

public class WindowRC implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        if ("Edit Customer".equals(e.getActionCommand())) {
            JFrame windowRC = new JFrame();
            JTable table = new JTable();
            JButton button = new JButton("Update Database");

            table.setBounds(268, 52, 283, 198);
            button.setBounds(350, 180, 100, 60);
            button.setFocusable(false);

            windowRC.add(button);
            windowRC.add(new JScrollPane(table));

            windowRC.setSize(750, 750);
            windowRC.getContentPane().setBackground(Color.WHITE);
            windowRC.setTitle("Remove Product Data");
            windowRC.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            windowRC.setVisible(true);
            windowRC.setLocationRelativeTo(null);

            try {
                Class.forName("com.mysql.cj.jdbc.Driver");
                Connection con = DriverManager.getConnection("jdbc:mysql://localhost/inventoryapp", "root", "P@kist@n1");
                Statement st = con.createStatement();
                String query = "SELECT * from addcustomer";
                ResultSet rs = st.executeQuery(query);
                ResultSetMetaData rsmd = rs.getMetaData();
                DefaultTableModel model = (DefaultTableModel) table.getModel();

                int cols = rsmd.getColumnCount();
                String[] colName = new String[cols];
                for (int i = 0; i < cols; i++)
                    colName[i] = rsmd.getColumnName(i + 1);
                model.setColumnIdentifiers(colName);

                String name, address, email, tel, fax;

                while (rs.next()) {
                    name = rs.getString(1);
                    address = rs.getString(2);
                    email = rs.getString(3);
                    tel = rs.getString(4);
                    fax = rs.getString(5);

                    String[] row = {name, address, email, tel, fax};
                    model.addRow(row);
                }
            } catch (ClassNotFoundException | SQLException classNotFoundException) {
                classNotFoundException.printStackTrace();
            }

            if ("Update Database".equals(e.getActionCommand()))
                System.out.println("Update happening!!!");
                button.addActionListener(new ActionListener() {
                    private Object Component;

                    @Override
                    public void actionPerformed(ActionEvent e1) {
                        try {
                            Class.forName("com.mysql.cj.jdbc.Driver");
                            Connection con = DriverManager.getConnection("jdbc:mysql://localhost/inventoryapp", "root", "P@kist@n1");
                            Statement st = con.createStatement();
                            DefaultTableModel model = (DefaultTableModel) table.getModel();
                            int row = table.getSelectedRow();

                            for (int i = 0; i < model.getRowCount(); i++) {
                                String name = (model.getValueAt(i, 0).toString());
                                String address = model.getValueAt(i, 1).toString();
                                String email = model.getValueAt(i, 2).toString();
                                String tel = model.getValueAt(i, 3).toString();
                                String fax = model.getValueAt(i, 4).toString();

                                PreparedStatement updateQuery = con.prepareStatement("UPDATE addcustomer" + "SET Name = ?" + "WHERE Name = ? "+ row);

                                updateQuery.setString(0,name);
                                updateQuery.setString(1,address);
                                updateQuery.setString(2,email);
                                updateQuery.setString(3,tel);
                                updateQuery.setString(4,fax);

                                updateQuery.executeUpdate();

                                st.close();
                                con.close();

                       JOptionPane.showMessageDialog((java.awt.Component) Component, "Data Edited");
                            }
                        } catch (ClassNotFoundException | SQLException classNotFoundException) {
                            classNotFoundException.printStackTrace();
                        }
                    }
                });
        }
    }
}

错误分析与修复步骤

1. 参数索引越界核心原因

PreparedStatement的参数索引从1开始计数,原代码中updateQuery.setString(0, name)直接触发索引越界错误。

2. UPDATE语句语法与逻辑错误

  • 字符串拼接时缺少空格,导致SQL语句变成UPDATE addcustomerSET Name = ?WHERE Name = ? 0,完全不符合语法规范。
  • 仅更新Name字段不符合需求,应该同步所有修改的字段。
  • WHERE条件用Name作为唯一标识不合理,若存在同名客户会批量误更新;末尾拼接row变量属于无效语法。

3. 资源管理错误

循环内部每次迭代都关闭Connection和Statement,第一次循环后连接就被关闭,后续迭代会抛出连接已关闭的异常。

4. 其他逻辑问题

  • 按钮监听器注册逻辑错误:if ("Update Database".equals(e.getActionCommand()))永远不会触发(事件来自"Edit Customer"菜单),且代码块未加大括号,导致逻辑混乱。
  • JOptionPane中的Component为null,会抛出类型转换异常。

修正后的代码

package com.company;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.*;

public class WindowRC implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        if ("Edit Customer".equals(e.getActionCommand())) {
            JFrame windowRC = new JFrame();
            JTable table = new JTable();
            JButton button = new JButton("Update Database");

            table.setBounds(268, 52, 283, 198);
            button.setBounds(350, 180, 150, 60);
            button.setFocusable(false);

            windowRC.add(button);
            windowRC.add(new JScrollPane(table));

            windowRC.setSize(750, 750);
            windowRC.getContentPane().setBackground(Color.WHITE);
            windowRC.setTitle("Edit Customer Data");
            windowRC.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // 改为关闭当前窗口而非退出程序
            windowRC.setVisible(true);
            windowRC.setLocationRelativeTo(null);

            // 加载数据到表格
            try {
                Class.forName("com.mysql.cj.jdbc.Driver");
                Connection con = DriverManager.getConnection("jdbc:mysql://localhost/inventoryapp", "root", "P@kist@n1");
                Statement st = con.createStatement();
                String query = "SELECT * from addcustomer";
                ResultSet rs = st.executeQuery(query);
                ResultSetMetaData rsmd = rs.getMetaData();
                DefaultTableModel model = (DefaultTableModel) table.getModel();

                int cols = rsmd.getColumnCount();
                String[] colName = new String[cols];
                for (int i = 0; i < cols; i++)
                    colName[i] = rsmd.getColumnName(i + 1);
                model.setColumnIdentifiers(colName);

                String name, address, email, tel, fax;
                while (rs.next()) {
                    name = rs.getString(1);
                    address = rs.getString(2);
                    email = rs.getString(3);
                    tel = rs.getString(4);
                    fax = rs.getString(5);
                    String[] row = {name, address, email, tel, fax};
                    model.addRow(row);
                }
                // 关闭资源
                rs.close();
                st.close();
                con.close();
            } catch (ClassNotFoundException | SQLException ex) {
                ex.printStackTrace();
            }

            // 注册更新按钮的监听器(修复原逻辑错误)
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e1) {
                    Connection con = null;
                    PreparedStatement updateQuery = null;
                    try {
                        Class.forName("com.mysql.cj.jdbc.Driver");
                        con = DriverManager.getConnection("jdbc:mysql://localhost/inventoryapp", "root", "P@kist@n1");
                        // 正确的UPDATE语句:更新所有字段,用Name作为条件(建议改为主键,比如id)
                        String sql = "UPDATE addcustomer SET address = ?, email = ?, tel = ?, fax = ? WHERE Name = ?";
                        updateQuery = con.prepareStatement(sql);

                        DefaultTableModel model = (DefaultTableModel) table.getModel();
                        int updatedRows = 0;

                        for (int i = 0; i < model.getRowCount(); i++) {
                            String name = model.getValueAt(i, 0).toString();
                            String address = model.getValueAt(i, 1).toString();
                            String email = model.getValueAt(i, 2).toString();
                            String tel = model.getValueAt(i, 3).toString();
                            String fax = model.getValueAt(i, 4).toString();

                            // 参数从1开始赋值
                            updateQuery.setString(1, address);
                            updateQuery.setString(2, email);
                            updateQuery.setString(3, tel);
                            updateQuery.setString(4, fax);
                            updateQuery.setString(5, name);

                            updatedRows += updateQuery.executeUpdate();
                        }

                        JOptionPane.showMessageDialog(windowRC, "成功更新 " + updatedRows + " 条数据");
                    } catch (ClassNotFoundException | SQLException ex) {
                        ex.printStackTrace();
                        JOptionPane.showMessageDialog(windowRC, "更新失败:" + ex.getMessage());
                    } finally {
                        // 确保资源关闭
                        try {
                            if (updateQuery != null) updateQuery.close();
                            if (con != null) con.close();
                        } catch (SQLException ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            });
        }
    }
}

额外优化建议

  1. 使用主键作为更新条件:建议给addcustomer表添加自增主键(如id INT AUTO_INCREMENT PRIMARY KEY),然后用WHERE id = ?作为更新条件,避免同名客户被误更新。
  2. 仅更新修改过的行:监听表格单元格编辑事件,记录修改过的行,只更新这些行,提升效率。
  3. 数据库连接复用:使用数据库连接池(如HikariCP)代替每次创建新连接,优化性能。
  4. 异常处理优化:将异常信息友好地展示给用户,而不是仅打印堆栈信息。

内容的提问来源于stack exchange,提问作者Uzair

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 08:31:18