2015-11-14 83 views
0

我正在使用连接到MySQL数据库的Swing应用程序。它从数据库中提取一些数据并显示在表格中。此外,有3个按钮,假设的变化表数据(添加行表),更新数据库(更新数据库),并放弃更改(放弃更改),如下图所示如何正确更新MySQL数据库的JTable数据?

enter image description here

点击后将行添加到表按钮,表格中的新条目应添加在表格中。之后,如果点击更新按钮,数据将在数据库中更新。放弃更改将从表的最后一行删除数据,并且与db无关。该应用程序有两类CoffeesFrame.javaCoffeesTableModel.java我提供来自两个下面的类的示例代码,

public class CoffeesFrame extends JFrame implements RowSetListener { 

    private static final long serialVersionUID = 1L; 

    private static Connection myConn = null; 
    private static String url = "jdbc:mysql://localhost:3306/myDemo"; 
    private static String user = "student"; 
    private static String password = "student"; 

    // initiate a table object 
    JTable table; 

// labels of the table 

// text data fields of the table 

// buttons of the table 


// initiate a table model object 
CoffeesTableModel myCoffeesTableModel; 

// table constructor 
public CoffeesFrame(Connection myConn) throws SQLException { 


    table = new JTable();  
    createNewTableModel(myConn); 

    /* 
     label, text field and buttons 
    */ 

    Container contentPane = getContentPane(); 
    contentPane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); 
    contentPane.setLayout(new GridBagLayout()); 
    GridBagConstraints c = new GridBagConstraints(); 

    /* 
    Code for making the GUI 
    */ 



    button_ADD_ROW.addActionListener(new ActionListener() { 

     public void actionPerformed(ActionEvent e) { 

      // showMessageDialog works 
      JOptionPane.showMessageDialog(CoffeesFrame.this, new String[] { 

        "Adding the following row:", 
        "Coffee name: [" + textField_COF_NAME.getText() + "]", 
        "Supplier ID: [" + textField_SUP_ID.getText() + "]", 
        "Price: [" + textField_PRICE.getText() + "]", 
        "Sales: [" + textField_SALES.getText() + "]", 
        "Total: [" + textField_TOTAL.getText() + "]" }); 

      try { 

       // Insert row is not adding data to the table 
       myCoffeesTableModel.insertRow(
         textField_COF_NAME.getText(), 
         Integer.parseInt(textField_SUP_ID.getText().trim()), 
         Float.parseFloat(textField_PRICE.getText().trim()), 
         Integer.parseInt(textField_SALES.getText().trim()), 
         Integer.parseInt(textField_TOTAL.getText().trim())); 

       // table.getModel(); 
      } 

      catch (Exception ex) { 

       ex.printStackTrace(); 
      } 
     } 

    }); 


    button_UPDATE_DATABASE.addActionListener(new ActionListener() { 

     public void actionPerformed(ActionEvent e) { 

      try { 

       myCoffeesTableModel.coffeesRowSet.acceptChanges(myConn); 
      } 

      catch (Exception ex) { 

       ex.printStackTrace(); 
      } 


      try { 

       createNewTableModel(myConn); 
      } 

      catch (Exception el) { 

       el.printStackTrace(); 
      } 

     } 
    }); 


    button_DISCARD_CHANGES.addActionListener(new ActionListener() { 

     public void actionPerformed(ActionEvent e) { 

      System.out.println("The changes are DISCARDED"); 
     } 
    }); 
} 



private void createNewTableModel(Connection myConn) throws SQLException { 

    myCoffeesTableModel = new CoffeesTableModel(getContentsOfCoffeesTable(myConn)); 
    myCoffeesTableModel.addEventHandlersToRowSet(this); 
    table.setModel(myCoffeesTableModel); 
    } 

@Override 
public void rowSetChanged(RowSetEvent event) { 

    // TODO Auto-generated method stub 
} 

@Override 
public void rowChanged(RowSetEvent event) { 

    // TODO Auto-generated method stub 
} 

@Override 
public void cursorMoved(RowSetEvent event) { 

    // TODO Auto-generated method stub 

} 

public CachedRowSet getContentsOfCoffeesTable(Connection mycConn) 
     throws SQLException { 

    CachedRowSet crs = null; 
    ResultSet resultSet = null; 
    Statement stmt = null; 
    String sql = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES"; 

    try { 

     stmt = myConn.createStatement(); 
     resultSet = stmt.executeQuery(sql); 

     crs = new CachedRowSetImpl(); 
     crs.populate(resultSet); 

    } 

    catch (Exception e) { 

     e.printStackTrace(); 
    } 

    return crs; 
} 


public static void main(String[] args) throws SQLException { 

    try { 

     myConn = DriverManager.getConnection(url, user, password); 

     if (myConn != null) { 

      System.out.println("Connected to the database myDemo"); 
     } 
    } 

    catch (SQLException ex) { 

     System.out 
       .println("An error occurred. Maybe user/password is invalid"); 
     ex.printStackTrace(); 
    } 

    myConn.setAutoCommit(false); 

    CoffeesFrame coffeesFrame = new CoffeesFrame(myConn); 
    coffeesFrame.pack(); 
    coffeesFrame.setVisible(true); 

} 

}

的CoffeesTableModel.java如下,//

public class CoffeesTableModel implements TableModel { 

CachedRowSet coffeesRowSet; // The ResultSet to interpret 
ResultSetMetaData metadata; // Additional information about the results 
int numcols, numrows; // How many rows and columns in the table 


public CoffeesTableModel(CachedRowSet rowSetArg) throws SQLException { 

    this.coffeesRowSet = rowSetArg; 
    this.metadata = this.coffeesRowSet.getMetaData(); 
    numcols = metadata.getColumnCount(); 

    // Retrieve the number of rows. 
    this.coffeesRowSet.beforeFirst(); 
    this.numrows = 0; 

    while (this.coffeesRowSet.next()) { 

     this.numrows++; 
    } 

    this.coffeesRowSet.beforeFirst(); 
} 

public CachedRowSet getCoffeesRowSet() { 

    return coffeesRowSet; 
} 

public void addEventHandlersToRowSet(RowSetListener listener) { 

    this.coffeesRowSet.addRowSetListener(listener); 
} 

public void insertRow(String coffeeName, int supplierID, float price, 
     int sales, int total) throws SQLException { 

    try { 

     this.coffeesRowSet.moveToInsertRow(); 
     this.coffeesRowSet.updateString("COF_NAME", coffeeName); 
     this.coffeesRowSet.updateInt("SUP_ID", supplierID); 
     this.coffeesRowSet.updateFloat("PRICE", price); 
     this.coffeesRowSet.updateInt("SALES", sales); 
     this.coffeesRowSet.updateInt("TOTAL", total); 
     this.coffeesRowSet.insertRow(); 
     this.coffeesRowSet.moveToCurrentRow(); 
    } 

    catch (SQLException e) { 

     e.printStackTrace(); 
     // JDBCTutorialUtilities.printSQLException(e); 
    } 
} 

public void close() { 

    try { 

     coffeesRowSet.getStatement().close(); 
    } 

    catch (SQLException e) { 

     e.printStackTrace(); 
     // JDBCTutorialUtilities.printSQLException(e); 
    } 
} 

/** Automatically close when we're garbage collected */ 
protected void finalize() { 

    close(); 
} 

/** Method from interface TableModel; returns the number of columns */ 

public int getColumnCount() { 

    return numcols; 
} 

/** Method from interface TableModel; returns the number of rows */ 
public int getRowCount() { 

    return numrows; 
} 

/** 
* Method from interface TableModel; returns the column name at columnIndex 
* based on information from ResultSetMetaData 
*/ 

public String getColumnName(int column) { 

    try { 

     return this.metadata.getColumnLabel(column + 1); 
    } 

    catch (SQLException e) { 

     return e.toString(); 
    } 
} 


/** 
* Method from interface TableModel; returns the most specific superclass 
* for all cell values in the specified column. To keep things simple, all 
* data in the table are converted to String objects; hence, this method 
* returns the String class. 
*/ 

public Class getColumnClass(int column) { 

    return String.class; 
} 

/** 
* Method from interface TableModel; returns the value for the cell 
* specified by columnIndex and rowIndex. TableModel uses this method to 
* populate itself with data from the row set. SQL starts numbering its rows 
* and columns at 1, but TableModel starts at 0. 
*/ 

public Object getValueAt(int rowIndex, int columnIndex) { 

    try { 

     this.coffeesRowSet.absolute(rowIndex + 1); 
     Object o = this.coffeesRowSet.getObject(columnIndex + 1); 

     if (o == null) 
      return null; 

     else 
      return o.toString(); 
    } 

    catch (SQLException e) { 

     return e.toString(); 
    }  
} 

/** 
* Method from interface TableModel; returns true if the specified cell is 
* editable. This sample does not allow users to edit any cells from the 
* TableModel (rows are added by another window control). Thus, this method 
* returns false. 
*/ 

public boolean isCellEditable(int rowIndex, int columnIndex) { 

    return false; 
} 

// Because the sample does not allow users to edit any cells from the 
// TableModel, the following methods, setValueAt, addTableModelListener, 
// and removeTableModelListener, do not need to be implemented. 

public void setValueAt(Object value, int row, int column) { 

    System.out.println("Calling setValueAt row " + row + ", column " 
      + column); 
} 

public void addTableModelListener(TableModelListener l) { 

} 

public void removeTableModelListener(TableModelListener l) { 

} 

} 

表中的数据显示从数据库中抓取并呈现为表格。 “将行添加到表”显示表单插入的弹出窗口,但不要将数据作为新行放在表的末尾。但是,我没有收到任何错误。 “更新数据库”按钮不起作用,并提供java.sql.SQLException:未指定表。。我如何改进代码?

回答

3

而不是实现TableModel接口,您应该从AbstractTableModel扩展,这有一些默认的功能,你不想复制的一些“正常”功能。

通过不提供作出通知其他观察员(如JTable

insertRow方法必须调用fireTableRowsInserted(从AbstractTableModel)的能力取出addTableModelListenerremoveTableModelListener,你当前的实现基本上已经打破了模型的合同为了通知JTable,该模型已发生变化,它需要自己用新的数据

Java使得不保证finalize将被称为更新,不依赖于它

getRowCount将受RowSet的大小影响,因此,您需要能够保持一个运行值(即您需要在添加新行时增加它)或计算RowSet本身的行数。我相信你可以将光标移动到末尾(或超越最后一个位置),并使用getRow做到这一点,不要忘了,虽然,ResultSet1基础的,不是基于0JTable预计

+0

你能提供一些示例代码? –

+1

[如何使用表格](http://docs.oracle.com/javase/tutorial/uiswing/components/table.html) – MadProgrammer

+0

非常感谢您的回复 –