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());
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?
A workaround could be to create your custom component that extends TableView and then do the magic inside your own CustomTableView class