javajavafxjavafx-2javafx-tableview

JavaFX TableView adding extra column for same data


I have a small app. With this app, I can add a new Employee record to a MySQL database and then display these records. buildData() retrieves data from the database and displays it in the TableView, I also call this method every time a new record is added to "refresh" the TableView. This however isn't behaving as expected.

This is the view after the first record is added:

enter image description here

when I hit the button to add another record, this is what I get:

enter image description here

If I close the app and reopen it, the TableView is normal:

enter image description here

This is what the buildData() method looks like (Method ignores Typechecking and all that.Probably the cause?)

private ObservableList<ObservableList> data;

public void buildData() {
    Connection c;
    TableColumn col;
    data = FXCollections.observableArrayList();
    try {

        c = DataBaseConnection.connectToDatabase();
        String SQL = "SELECT * FROM employees";

        ResultSet rs = c.createStatement().executeQuery(SQL);

        for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {

            final int j = i;
            col = new TableColumn(rs.getMetaData().getColumnName(i + 1));
            col.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ObservableList, String>, ObservableValue<String>>() {
                public ObservableValue<String> call(TableColumn.CellDataFeatures<ObservableList, String> param) {
                    return new SimpleStringProperty(param.getValue().get(j).toString());
                }
            });
            employeeTableView.getColumns().addAll(col);
        }
        while (rs.next()) {

            ObservableList<String> row = FXCollections.observableArrayList();
            for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
                row.add(rs.getString(i));
            }
            data.add(row);
        }
        employeeTableView.setItems(data);

    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("Error on Building Data");
    }
}

and then the method to add a new Employee Record to the database:

 public void addEmployeeToDatabase() {

    Employee employee = new Employee("Anne Droid", "Marketing", "Gender");

    String query = "INSERT INTO employees (Employee_Name, Department, Gender) VALUES (?, ? , ?)";

    try {
        preparedStatement = connection.prepareStatement(query);

        preparedStatement.setString(1, employee.getEmployeeName());
        preparedStatement.setString(2, employee.getDepartment());
        preparedStatement.setString(3, employee.getGender());
        preparedStatement.execute();

        buildData();
        connection.close();

    } catch (SQLException e) {
        e.printStackTrace();
    }
}

Finally, the Employee class:

public class Employee {

private StringProperty employeeName;
private StringProperty department;
private StringProperty gender;

public Employee() {

}

public Employee(String employeeName, String department, String gender) {
    this.employeeName = new SimpleStringProperty(employeeName);
    this.department = new SimpleStringProperty(department);
    this.gender = new SimpleStringProperty(gender);
}

public String getEmployeeName() {
    return employeeName.get();
}

public StringProperty employeeNameProperty() {
    return employeeName;
}
...

Am using pure java, no FXML.I've searched for a solution, but none is available (As far as I can tell). Any pointers?


Solution

  • In the buildData method you replace the items. However you add new TableColumns to the columns list without removing any columns. This way the number of columns is increased every time you call the buildData method.

    Clear the columns list before adding new columns to fix this:

    ...
    
    ResultSet rs = c.createStatement().executeQuery(SQL);
    
    employeeTableView.getColumns().clear();
    
    for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
    
        final int j = i;
        col = new TableColumn(rs.getMetaData().getColumnName(i + 1));
    
        ...
    
        employeeTableView.getColumns().add(col);
    }
    
    ...