title: How to update JTable data with MySQL database properly?
body: <p>I'm working on a Swing app which is connected to MySQL database. It fetches some data from the DB and shows in the table. Besides, there are 3 buttons that suppose to changes table data ( Add row to table ), update the database (Update database ) and to discard the changes ( Discard changes ) as following, </p>
  
  <p><a href="https://i.stack.imgur.com/FdR8W.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/FdR8W.png" alt="enter image description here"></a></p>
  
  <p>After clicking the <em>Add row to table</em> button, the new entries from the form should be added in the table. Afterwards if the update button is clicked, the data will be updated in the db. Discard changes will delete the data from the last row of the table and will have nothing to do with db. The app has two classes <em>CoffeesFrame.java</em> and <em>CoffeesTableModel.java</em> I provided the sample code from both of the classes below,</p>
  
  <pre><code>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);
  
  }
  </code></pre>
  
  <p>}</p>
  
  <p>The CoffeesTableModel.java as follows, //</p>
  
  <pre><code>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) {
  
  }
  
  }
  </code></pre>
  
  <p>The data shows in the table is grabbed from the db and presented as table. The "Add row to table" shows the pop-up from the form insertion but don't put the data as new row in the end of the table. However, I'm not getting any error. The "Update database" button is not working and provides <em>java.sql.SQLException: Table not specified.</em>. How can I improve the code ? </p>