【问题标题】:Inserting data to JavaFX TableView without intermediate class在没有中间类的情况下将数据插入 JavaFX TableView
【发布时间】:2023-03-20 12:43:01
【问题描述】:

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

这是我使用中间类 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;
}

控制器

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());

【问题讨论】:

    标签: java javafx tableview resultset


    【解决方案1】:

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

    它不一定是你创建的类,但如果你只是使用一些通用的东西,你的代码会更难理解。例如,您可以只使用 List&lt;String&gt; 来保存每一行:

    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)) ;
        }
    });
    

    然后

    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;
    }
    

    但是现在您的代码几乎完全没有您所表示的数据的语义。

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

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

    【讨论】:

    • 这对性能有中等影响。每次请求单元格值时,您都会创建一个新的ReadOnlyStringWrapper。例如,在我的 ~20000 条目表上对一行进行排序时,单元格值工厂被调用了大约 450.000 次。不幸的是,似乎没有办法将字符串传递给单元值工厂。
    • @Marv 正确。正如我在帖子底部建议的那样,最好创建一个数据模型类并遵循预期的模式。
    • 我同意。不幸的是,即使对于不可变或派生值,这也会迫使您拥有属性,这会迫使您承担不必要的开销。例如,想要在模型类中显示字符串列表的第一项会有点让人头疼,除非它是ObservableStringValues 的列表。我猜属性是相对轻量级的,但仍然是。
    • @Marv 好吧,你真正需要的是ObservableValue,而不是Property;因此,如果您需要优化,您可以自己提供一个非常小的实现。与普通值相比,这仍然是一些开销,但几乎没有(例如,对于不可变的值,您的添加/删除侦听器可能是无操作的,您只需实现 getValue() 以返回该值)。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2019-05-14
      • 1970-01-01
      • 2018-05-10
      • 2022-07-02
      • 2022-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多