不使用中间类将数据插入JavaFX TableView

不使用中间类将数据插入JavaFX TableView,java,javafx,tableview,resultset,Java,Javafx,Tableview,Resultset,我是Java程序员新手。 我想将ResultSet数据插入JavaFXTableView,但不使用中间类。我可以将结果集行作为对象插入到TableView行中吗 下面是我使用中间类单元的代码 public static ObservableList<Unit> getUnits() { final ObservableList<Unit> data = FXCollections.observableArrayList(); if (openConne

我是Java程序员新手。 我想将ResultSet数据插入JavaFXTableView,但不使用中间类。我可以将结果集行作为对象插入到TableView行中吗

下面是我使用中间类单元的代码

 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;
}
publicstaticobserveListGetUnits(){
最终ObservableList数据=FXCollections.observableArrayList();
if(openConnection()){
试一试{
rs=st.executeQuery(“从单位中选择*);
while(rs.next()){
添加(新单位(rs.getString(“id_单位”),
rs.getString(“短名称”),
rs.getString(“名称”);
}
}捕获(例外情况除外){
Logger.getLogger(SQLConnect.class.getName()).log(Level.SEVERE,null,ex);
}
}
closeConnection();
返回数据;
}
控制器

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());
idUnit.setCellValueFactory(新属性值工厂(“idUnit”);
setCellValueFactory(新属性ValueFactory(“shortName”);
nameUnit.setCellValueFactory(新属性ValueFactory(“名称”);
setItems(SQLConnect.getUnits());

一种解决方法是创建扩展TableView的自定义组件,然后在自己的CustomTableView类中发挥神奇的作用

您需要一些东西来保存数据;某些东西(您称之为“中间类”)将成为您的
TableView
的数据类型

它不一定是您创建的类,但是如果您只是使用一些通用的东西,您的代码将更难理解。例如,您可以只使用
列表
来保存每一行:

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)) ;
    }
});
TableView unitsTableView=newtableview();
idUnit=新表列(“Id”);
idUnit.setCellValueFactory(新回调(){
@凌驾
公共observeValue调用(CellDataFeatures>data){
返回新的ReadOnlyStringWrapper(data.getValue().get(0));
}
});
shortNameUnit=新表列(“短名称”);
setCellValueFactory(新回调(){
@凌驾
公共observeValue调用(CellDataFeatures>data){
返回新的ReadOnlyStringWrapper(data.getValue().get(1));
}
});
名称单位=新表列(“名称”);
nameUnit.setCellValueFactory(新回调(){
@凌驾
公共observeValue调用(CellDataFeatures>data){
返回新的ReadOnlyStringWrapper(data.getValue().get(2));
}
});
然后

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;
}
publicstaticobserveListGetUnits(){
最终ObservableList数据=FXCollections.observableArrayList();
if(openConnection()){
试一试{
rs=st.executeQuery(“从单位中选择*);
while(rs.next()){
列表单位=新的ArrayList();
添加(rs.getString(“id_unit”);
添加(rs.getString(“短名称”);
添加(rs.getString(“名称”);
数据。添加(单位);
}
}捕获(例外情况除外){
Logger.getLogger(SQLConnect.class.getName()).log(Level.SEVERE,null,ex);
}
}
closeConnection();
返回数据;
}
但现在,您的代码几乎完全缺乏所表示数据的语义

请注意,由于多种原因,您不能直接使用
ResultSet
。一种是TableView中的数据由随机访问列表表示。虽然您可以将
ResultSet
视为表示数据行列表,但它没有实现
list
接口,也没有任何随机访问功能(无法保证获得第5行等)。另一个原因是
ResultSet
需要(或者至少可能需要,取决于JDBC驱动程序实现)一个实时数据库资源。因此,在TableView处于作用域的整个时间内,您都有可能锁定数据库表


为什么要避免创建数据表示类?

这对性能影响不大。每次请求单元格值时,您都会创建一个新的
ReadOnlyStringWrapper
。例如,在我的~20000条目的表格中对一行进行排序时,单元格值工厂被调用大约450.000次。不幸的是,似乎没有办法将字符串传递给单元格值工厂。@Marv Correct。正如我在文章底部所建议的,最好创建一个数据模型类并遵循预期的模式。我同意。不幸的是,这迫使您甚至拥有不可变或派生值的属性,这会迫使您承担不必要的开销。例如,想要在模型类中显示字符串列表的第一项就有点麻烦了,除非它是
observeStringValue
s的列表。我想属性是相对轻量级的,但仍然是。@Marv好吧,你真正需要的是一个
observeValue
,而不是
属性
;因此,如果需要优化,您可以自己提供一个非常小的实现。与普通值相比,它仍然有一些开销,但几乎没有(例如,对于不可变值,您的添加/删除侦听器可能没有操作,您只需实现
getValue()
来返回值)。