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

Java Swing中JTable点击按钮后不更新数据库数据问题求助

Java Swing JTable 点击按钮后不更新数据库数据的问题

我开发了一个Java Swing应用,该应用从数据库获取数据并展示在JTable中。目前仅尝试查看数据库中的全部数据,但点击按钮发送查询请求后,JTable并未更新数据。已尝试重新加载Model以及调用model.fireTableDataChanged();方法,但问题仍未解决。


现有代码:

TableData.java

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

public class TableData extends JPanel {
    private JTable table;
    private DefaultTableModel model;
    private final Object Column[] = {"id", "titolo", "autore", "prezzo"};
    TableData(){
        model = new DefaultTableModel();
        table = new JTable(model);
        model.setColumnIdentifiers(Column);
        setLayout(new BorderLayout());
        add(new JScrollPane(table), BorderLayout.CENTER);
    }
    public void updateTable(Object row[]){
        model.addRow(row);
    }
}

ConnectionDB.java

import java.sql.Statement;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Connection;

public class ConnectionDB {
    private String url = "jdbc:mysql://localhost:4444/database_name";
    private String user = "root";
    private String password = "password";
    TableData tableData = new TableData();
    //id titolo autore prezzo
    public void upload_data(String titolo, String autore, int prezzo){
        try{
            Connection con = DriverManager.getConnection(url, user, password);
            Statement statement = con.createStatement();
            String query = "insert into libri(titolo, autore, prezzo)" +
                           "values ('"+titolo+"','"+autore+"','"+prezzo+"')";
            statement.executeUpdate(query);
            System.out.println("success");
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
    public void get_data(){
        Object row[] = new Object[4];
        try{
            Connection conn = DriverManager.getConnection(url, user, password);
            Statement statement = conn.createStatement();
            ResultSet resultSet = statement.executeQuery("select * from libri");
            while(resultSet.next()){
                for(int i = 1; i<=4; i++){
                    row[i-1] = resultSet.getString(i);
                }
                tableData.updateTable(row);
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}

PanelForm.java

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class PanelForm extends JPanel {
    private JButton buttonVisualizza;
    ConnectionDB conn = new ConnectionDB();

    public PanelForm(){
        // 示例组件初始化(根据实际代码补充)
        buttonVisualizza = new JButton("Visualizza");
        add(buttonVisualizza);
        
        buttonVisualizza.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                conn.get_data();
            }
        });
    }
}

HomePage.java

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

public class HomePage extends JFrame {
    private PanelForm panelForm;
    private TableData tableData;
    HomePage(){
        super("Home");
        setSize(800,500);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocation(200,200);
        setLayout(new BorderLayout());

        panelForm = new PanelForm();
        tableData = new TableData();
        add(panelForm, BorderLayout.LINE_START);
        add(tableData, BorderLayout.CENTER);
        setVisible(true);

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(HomePage::new);
    }
}

问题根源

ConnectionDB类中自行创建了一个TableData实例:TableData tableData = new TableData();,但这个实例从未被添加到界面中。点击按钮调用get_data()时,数据被添加到了这个看不见的TableData里,而界面上的TableData实例完全没有接收到数据更新。


解决方案

1. 修改ConnectionDB,通过构造方法传入界面上的TableData实例

不再自行创建TableData,而是使用界面上已经存在的实例:

import java.sql.*;

public class ConnectionDB {
    private String url = "jdbc:mysql://localhost:4444/database_name";
    private String user = "root";
    private String password = "password";
    private TableData tableData;

    // 构造方法传入界面上的TableData实例
    public ConnectionDB(TableData tableData) {
        this.tableData = tableData;
    }

    public void upload_data(String titolo, String autore, int prezzo){
        // 使用PreparedStatement避免SQL注入,同时自动关闭资源
        String query = "insert into libri(titolo, autore, prezzo) values (?, ?, ?)";
        try(Connection con = DriverManager.getConnection(url, user, password);
            PreparedStatement pstmt = con.prepareStatement(query)){
            pstmt.setString(1, titolo);
            pstmt.setString(2, autore);
            pstmt.setInt(3, prezzo);
            pstmt.executeUpdate();
            System.out.println("success");
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }

    public void get_data(){
        // 先清空表格旧数据,避免重复添加
        tableData.getModel().setRowCount(0);
        Object row[] = new Object[4];
        // try-with-resources自动关闭Connection、Statement、ResultSet
        try(Connection conn = DriverManager.getConnection(url, user, password);
            Statement statement = conn.createStatement();
            ResultSet resultSet = statement.executeQuery("select * from libri")){
            while(resultSet.next()){
                // 根据字段类型选择对应get方法,避免类型转换问题
                row[0] = resultSet.getInt(1);
                row[1] = resultSet.getString(2);
                row[2] = resultSet.getString(3);
                row[3] = resultSet.getDouble(4);
                tableData.updateTable(row);
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}

2. 给TableData添加获取Model的方法

方便外部清空表格数据:

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

public class TableData extends JPanel {
    private JTable table;
    private DefaultTableModel model;
    private final Object Column[] = {"id", "titolo", "autore", "prezzo"};

    TableData(){
        model = new DefaultTableModel();
        table = new JTable(model);
        model.setColumnIdentifiers(Column);
        setLayout(new BorderLayout());
        add(new JScrollPane(table), BorderLayout.CENTER);
    }

    public void updateTable(Object row[]){
        model.addRow(row);
    }

    // 新增方法:返回表格Model,供外部操作
    public DefaultTableModel getModel() {
        return model;
    }
}

3. 修改PanelForm,通过构造方法传入ConnectionDB实例

避免在PanelForm中自行创建ConnectionDB,确保使用的是绑定了界面TableData的实例:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class PanelForm extends JPanel {
    private JButton buttonVisualizza;
    private ConnectionDB conn;

    // 构造方法传入ConnectionDB实例
    public PanelForm(ConnectionDB conn) {
        this.conn = conn;
        buttonVisualizza = new JButton("Visualizza");
        add(buttonVisualizza);

        buttonVisualizza.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // 调用查询方法
                conn.get_data();
            }
        });
    }
}

4. 修改HomePage,完成实例绑定

将界面的TableData传给ConnectionDB,再把ConnectionDB传给PanelForm,确保所有组件使用同一个实例:

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

public class HomePage extends JFrame {
    private PanelForm panelForm;
    private TableData tableData;
    private ConnectionDB conn;

    HomePage(){
        super("Home");
        setSize(800,500);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLocation(200,200);
        setLayout(new BorderLayout());

        // 先创建TableData
        tableData = new TableData();
        // 创建ConnectionDB并绑定界面的TableData
        conn = new ConnectionDB(tableData);
        // 创建PanelForm并绑定ConnectionDB
        panelForm = new PanelForm(conn);

        add(panelForm, BorderLayout.LINE_START);
        add(tableData, BorderLayout.CENTER);
        setVisible(true);
    }

    public static void main(String[] args) {
        // 在EDT线程中启动Swing应用,符合Swing线程安全规范
        SwingUtilities.invokeLater(HomePage::new);
    }
}

额外优化建议

  1. 线程安全:数据库查询是耗时操作,建议使用SwingWorker在后台线程执行,避免阻塞UI线程导致界面卡顿。
  2. 资源管理:始终使用try-with-resources自动关闭数据库连接、Statement、ResultSet,防止资源泄漏。
  3. SQL注入防护:所有数据库操作都使用PreparedStatement代替字符串拼接,避免SQL注入风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:35:54