如何正确更新MySQL数据库的JTable数据?

时间:2015-11-14 07:05:25

标签: java mysql swing

我正在使用连接到MySQL数据库的Swing应用程序。它从数据库中获取一些数据并显示在表中。此外,还有3个按钮,用于更改表数据(添加行到表),更新数据库(更新数据库)和丢弃更改(放弃更改),如下所示,

enter image description here

单击向表中添加行按钮后,表单中的新条目应添加到表中。之后,如果单击更新按钮,数据将在db中更新。放弃更改将删除表的最后一行中的数据,并且与db无关。该应用程序有两个类 CoffeesFrame.java CoffeesTableModel.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:未指定表。。我该如何改进代码?

1 个答案:

答案 0 :(得分:3)

您应该从TableModel扩展而不是实现AbstractTableModel接口,而是具有某些" normal"的默认功能。您不想复制的功能。

删除addTableModelListenerremoveTableModelListener,您当前的实施基本上违反了模型的合同,因为它无法向其他观察者发送通知(例如JTable

您的insertRow方法必须致电fireTableRowsInserted(来自AbstractTableModel),以便通知JTable模型已更改,并且需要使用新版本更新自己数据

Java不保证finalize将被调用,不依赖它

getRowCount将受RowSet的大小影响,因此,您需要能够保持运行值(即,您需要在添加新行时增加它)或计算RowSet本身的行数。我相信你可以通过将光标移动到末尾(或超出最后位置)并使用getRow来做到这一点,不要忘记,ResultSet是基于1的,不是基于0期望

JTable