为了使用TableView,是否需要为每个数据库查询创建类?

人气:488 发布:2022-10-16 标签: sql java oop javafx tableview

问题描述

在过去的几天里,我学习了一些关于JavaFX的教程,解释如何使用TableView?每个教程都为example创建了类似Person的DataModel对象。只要您只需要像select Firstname, Lastname from Person这样的SQL语句就可以了。

但是,如果您不想为每个SELECT查询创建数据模型,因为您出于某种原因将数据与其他对象联接起来,该怎么办呢?例如,select * from Person join City join Country。前几天我学到的是,如果创建一个只包含List(表示行)的表视图,处理格式甚至计算表视图都会变得很糟糕。

这真的是JavaFX的事情吗?还是我错过了什么?

更新

为了更清楚,请参阅question。我是在阅读对我的问题的回答和评论后首次发现此问题的,但我对链接问题的答案不满意。

SQL

您的问题在这里混淆了两个概念:一方面是javafx.scene.control.TableView,另一方面是推荐答案/ORM。让我们忘掉SQL查询,比如我认为您最关心的是TableView

TableView必须填充List。此列表的内部类型必须与TableView的泛型类型匹配。因此,例如TableView<Person>将使用List<Person>填充。

除此之外,表示行的对象的实际类型可以是任何类型。它甚至不必包含数据本身,或者它可以是一个Map<String, Object>。在本例中,您将通过为每一列定义一个CellValueFactory来将该行的键映射到每一列,该CellValueFactory将返回您选择的键的入口值。

然后,您可以通过为列定义CellFactory将此值转换为String和/或Node

具有JavaFX属性的对象可以更容易地映射,因为存在仅需要属性名称的预制PropertyValueFactory。但它们并不是唯一的出路。

为每行使用Map<String, Object>的示例:

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仅用于演示。如果我没有设置它,则Integer单元格将呈现为调用Integer.toString()单元格text属性。

538