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); } }
额外优化建议
- 线程安全:数据库查询是耗时操作,建议使用
SwingWorker在后台线程执行,避免阻塞UI线程导致界面卡顿。 - 资源管理:始终使用
try-with-resources自动关闭数据库连接、Statement、ResultSet,防止资源泄漏。 - SQL注入防护:所有数据库操作都使用
PreparedStatement代替字符串拼接,避免SQL注入风险。
内容的提问来源于stack exchange,提问作者user19230297
相关产品推荐
相关产品推荐

