Inserting data to JavaFX TableView without interme

2019-02-22 10:23发布

问题:

I'm newbie Java programmer. I would like to insert ResultSet data to JavaFX TableView, but i wouldn't use intermediate class. Can i insert ResultSet rows to TableView rows as objects?

Here is my code with using intermediate class Unit

 public static ObservableList<Unit> getUnits() {

    final ObservableList<Unit> data = FXCollections.observableArrayList();
    if (openConnection()) {
        try {
            rs = st.executeQuery("SELECT * FROM units");
            while (rs.next()) {

                data.add(new Unit(rs.getString("id_unit"),
                        rs.getString("short_name"),
                        rs.getString("name")));
            }
        } catch (Exception ex) {
            Logger.getLogger(SQLConnect.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    closeConnection();
    return data;
}

Controller

idUnit.setCellValueFactory(new PropertyValueFactory<Unit, String>("idUnit"));
shortNameUnit.setCellValueFactory(new PropertyValueFactory<Unit, String>("shortName"));
nameUnit.setCellValueFactory(new PropertyValueFactory<Unit, String>("name"));

unitsTableView.setItems(SQLConnect.getUnits());

回答1:

You need something to hold the data; that something (which you call the "intermediate class") is going to be the data type for your TableView.

It doesn't necessarily have to be a class you create, but if you just use something general, your code is going to be much harder to understand. For example, you could just use a List<String> to hold each row:

TableView<List<String>> unitsTableView = new TableView<>();
idUnit = new TableColumn<List<String>, String>("Id");
idUnit.setCellValueFactory(new Callback<CellDataFeatures<List<String>, String>, ObservableValue<String>>() {
    @Override
    public ObservableValue<String> call(CellDataFeatures<List<String>, String>> data) {
        return new ReadOnlyStringWrapper(data.getValue().get(0)) ;
    }
});
shortNameUnit = new TableColumn<List<String>, String>("Short Name");
shortNameUnit.setCellValueFactory(new Callback<CellDataFeatures<List<String>, String>, ObservableValue<String>>() {
    @Override
    public ObservableValue<String> call(CellDataFeatures<List<String>, String>> data) {
        return new ReadOnlyStringWrapper(data.getValue().get(1)) ;
    }
});
nameUnit = new TableColumn<List<String>, String>("Name");
nameUnit.setCellValueFactory(new Callback<CellDataFeatures<List<String>, String>, ObservableValue<String>>() {
    @Override
    public ObservableValue<String> call(CellDataFeatures<List<String>, String>> data) {
        return new ReadOnlyStringWrapper(data.getValue().get(2)) ;
    }
});

and then

public static ObservableList<List<String>> getUnits() {

    final ObservableList<List<String>> data = FXCollections.observableArrayList();
    if (openConnection()) {
        try {
            rs = st.executeQuery("SELECT * FROM units");
            while (rs.next()) {
                List<String> unit = new ArrayList<>();
                unit.add(rs.getString("id_unit"));
                unit.add(rs.getString("short_name"));
                unit.add(rs.getString("name"));
                data.add(unit);
            }
        } catch (Exception ex) {
            Logger.getLogger(SQLConnect.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    closeConnection();
    return data;
}

But now your code is almost completely devoid of the semantics of the data you are representing.

Note that you can't use a ResultSet directly, for a number of reasons. One is that the data in the TableView are represented by a random-access list. While you can think of ResultSet as representing a list of rows of data, it doesn't implement the List interface, and doesn't have any random-access functionality (there's no guaranteed way to get row number 5, etc.). Another reason is that a ResultSet requires (or at least may require, depending on the JDBC driver implementation) a live database resource. So you would risk locking your database table for the entire time the TableView is in scope.

Why do you want to avoid creating the data representation class?



回答2:

A workaround could be to create your custom component that extends TableView and then do the magic inside your own CustomTableView class