Your question is mixing up two concepts here: javafx.scene.control.TableView on one hand, and SQL/ORM on the other hand. Let's forget about SQL queries and such as I think your concern is mostly on TableView.
TableView must be populated with a List. The inner type of this list must match the TableView's generic type. So for instance TableView<Person> will be populated with a List<Person>.
Other than that, the actual type of the objects representing rows can be anything. It doesn't even have to contain the data itself, or it can very-well be, for instance, a Map<String, Object>. In this case, you will map the keys of the row to each column by defining a CellValueFactory for each column, that will return the entry value for your chosen key.
Then you can convert this value to a String and/or a Nodeby defining a CellFactory for the column.
Objects with JavaFX properties can be mapped more easily, as there exists pre-made PropertyValueFactory that will require only the property name. But they're not the only way to go.
Example using a Map<String, Object> for each row:
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Scene;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class App extends Application {
private TableView<Map<String, Object>> tableView;
private TableColumn<Map<String, Object>, String> nameCol;
private TableColumn<Map<String, Object>, Integer> ageCol;
private Stage stage;
@Override
public void start(Stage stage) {
this.stage = stage;
//Insert a TableView into scene
this.tableView = new TableView<>();
this.nameCol = new TableColumn<>("Name");
this.nameCol.setPrefWidth(250);
ageCol = new TableColumn<>("Age");
tableView.getColumns().add(nameCol);
tableView.getColumns().add(ageCol);
nameCol.setCellValueFactory(param -> {
Map<String, Object> v = param.getValue();
return new SimpleStringProperty(v == null ? null : (String) v.get("name"));
});
ageCol.setCellValueFactory(param -> {
Map<String, Object> v = param.getValue();
return new SimpleObjectProperty<Integer>(v == null ? null : (Integer) v.get("age"));
});
ageCol.setCellFactory(param -> {
return new TableCell<>() {
@Override
public void updateItem(Integer item, boolean empty) {
if (empty || item == null)
super.setText("");
else
super.setText(NumberFormat.getIntegerInstance().format(item));
//Could also call setGraphic(Node)
}
};
});
final Scene scene = new Scene(new BorderPane(tableView), 640, 480);
stage.setScene(scene);
stage.setOnShown(event -> stageReady()); //Continue when stage is rendered
stage.show();
}
private void stageReady() {
//Generate data
List<Map<String, Object>> data = new ArrayList<>();
Map<String, Object> obj1 = new HashMap<>();
obj1.put("name", "Name of Object 1");
obj1.put("age", 42);
data.add(obj1);
Map<String, Object> obj2 = new HashMap<>();
obj2.put("name", "OBJECT 2");
obj2.put("age", 53);
data.add(obj2);
//Show data
tableView.getItems().setAll(data);
}
public static void main(String[] args) {
launch();
}
}
ageCol.setCellFactory is only here for demonstration. If I had not set it, then the Integer cells would have been rendered calling Integer.toString() for the cells text property.