在运行时为TableView动态分配列类型

时间:2019-03-23 21:38:08

标签: java generics javafx tableview

我正在使用JavaFX编写程序,这是一种向任意数据库提交任意SQL语句的简单方法。可以将其视为ScriptRunner的GUI版本。查询在后台线程中运行。

我不知道在编译时需要的列数和类型。实际上,直到我从数据库取回ResultSet时,我才知道ResultSet中的内容。在这一点上,我想针对其JDBC数据类型适当地处理数据。例如,我为每列分配一个Comparator,以便用户可以对任何列上显示的数据进行排序,并且数据将正常运行。

我在StackOverflow上找到了关键代码(尽管此后我丢失了该帖子的链接)。我非常感谢那个帖子。该代码有效,但效果并不令人满意,主要是因为它使用“原始类型”并取消选中强制转换。从那时起,我进行了一些更改以尝试对其进行改进,但可能适得其反。如果有人可以帮助我解决这个问题,我将不胜感激。当然,还有一种更优雅的方法。如果这一切尽善尽美,那也是很好的信息。

顺便说一句,我的整个项目都位于.java文件中:我不使用FXML或.css。

此示例代码中的main()仅用于调用processRequest()中的代码。

我所追求的主要是如何最好地声明和操作变量:“数据”,“列”和“ tvResult”。以及是否还有其他特殊考虑。     tvResult:在GUI中显示的内容。     data:在ResultSet(dah)中返回的数据。
    列:来自ResultSetMetaData的有关列的元数据。

我拥有的是:

ObservableList<ObservableList<?>> data = FXCollections.observableArrayList();
ArrayList<TableColumn<?,?>> columns = new ArrayList<>();
private TableView<ObservableList<?>> tvResult;

代码是我从各种教程,StackOverflow答案,书籍,博客等中收集的(请注意数据中的“ vogella.com”)。

表中的数据:

SQL:“从example.comments中选择*”。

输出: 1 || lars || myemail@gmail.com || http:\ www.vogella.com || 2009-09-14 ||摘要||我的第一条评论|| 2 ||斯蒂芬|| youremail@gmail.com || http:\ www.google.com || 2018-11-20 ||您的摘要在这里||您的第一条评论||

道歉 抱歉,这里有太多代码,我已尽力减少了代码,仍然有一个工作程序演示该问题。我剥离了在单独的线程,GUI内容和其他优点中运行的内容,以便我们可以专注于与我有关的代码。

它仍然比严格必要的时间长一点,但这是因为我想对processRequest()进行尽可能少的更改。它在String和Connection对象中接收SQL,并操纵提到的三个变量。

public class MySQLAccess extends Application {
    ObservableList<ObservableList<?>> data = FXCollections.observableArrayList();
    ArrayList<TableColumn<?,?>> columns = new ArrayList<>();
    private TableView<ObservableList<?>> tvResult;
    static MySQLAccess pgm;

/* ********************************************************************** **
**  main()
** ********************************************************************** */
    public static void main(String[] args) {
        pgm = new MySQLAccess();
        pgm.tvResult = new TableView<>();
        Connection connection = null;
        MysqlDataSource mySqlDataSource = new MysqlDataSource();
        mySqlDataSource.setUrl("jdbc:mysql://" + "localhost" + ":3306/" + "StackOverflow");
        mySqlDataSource.setUser("root");
        mySqlDataSource.setPassword("");
        DataSource dataSource = mySqlDataSource;
        try {
            connection = dataSource.getConnection();
            pgm.processRequest("select * from example.comments", connection);
        } catch (Exception e) {
            System.out.println("error creating connection");
        }
        pgm.tvResult.getColumns().clear();
        for (int j = 0; j < pgm.columns.size(); j++) {
            TableColumn<?, ?> col = pgm.columns.get(j);
            pgm.tvResult.getColumns().add((TableColumn<ObservableList<?>, ?>) col);
        }
        pgm.tvResult.setItems(pgm.data);

        ObservableList<TableColumn<ObservableList<?>,?>> columns = pgm.tvResult.getColumns();
        for (Object row : pgm.tvResult.getItems()) {
            for (TableColumn column : columns) {
                System.out.print(column.getCellObservableValue(row).getValue().toString() + " || ");
            }
            System.out.println();
        }
    }

/* ********************************************************************** **
**  processRequest()
** ********************************************************************** */
    private void processRequest(String sql, Connection connection) throws SQLException {
        Statement statement = connection.createStatement();
        ResultSet rs = statement.executeQuery(sql);
        ResultSetMetaData rm = rs.getMetaData();

//  Process Columns (assign the proper type to each)
        int colCnt = rm.getColumnCount();
        pgm.columns.clear();
        for (int i = 0; i < colCnt; i++) {
            final int k = i;
            String columnName = rm.getColumnName(i + 1);
            int columnType = rm.getColumnType(i + 1);
            TableColumn col = new TableColumn(columnName);
            col.setComparator(getComparator(columnType));
            col.setCellValueFactory(
                    new Callback<CellDataFeatures<ObservableList<?>, String>, ObservableValue<String>>() {
                        @Override
                        public ObservableValue<String> call(
                                CellDataFeatures<ObservableList<?>, String> param) {
                            return new SimpleStringProperty(
                                    param.getValue().get(k).toString());
                        }
                    });
            pgm.columns.add(col);
        }

//  Process Rows
        pgm.data.clear();
        while (rs.next()) {
            ObservableList<String> row = FXCollections.observableArrayList();
            row.clear();
            for (int i = 0; i < colCnt; i++) {
                String str;
                String hold = rs.getString(i + 1);
                if ((hold == null) || (hold.isEmpty())) {
                    str = "";
                } else {
                    str = String.valueOf(rs.getString(i + 1));
                }
                row.add(str);
            }
            pgm.data.add(row);
        }
    }

/* ********************************************************************** **
** getComparator()
** ********************************************************************** */
            private Comparator<?> getComparator(int columnType) {
                Comparator<?> comparator = null;
                String objectType = DataTypeMapping.javaClass(columnType);

                if (objectType.equals("String")) {
                    comparator = ((str_1, str_2) -> {
                        String int_1 = (String) str_1;
                        String int_2 = (String) str_2;
                        return int_1.compareTo(int_2);
                    });
                } else if (objectType.equals("Integer")) {
                    comparator = ((str_1, str_2) -> {
                        Integer int_1 = Integer.parseInt((String) str_1);
                        Integer int_2 = Integer.parseInt((String) str_2);
                        return int_1.compareTo(int_2);
                    });
                } else if (objectType.equals("Date")) {
                    comparator = ((str_1, str_2) -> {
                        Long date_1 = Long.parseLong((String) str_1);
                        Long date_2 = Long.parseLong((String) str_2);
                        return date_1.compareTo(date_2);
                    });
//
//                  .
//                  .
//                  .
//
                } else {
                    comparator = null;
                }
                return comparator;
            }

/* ********************************************************************** **
**  start()
** *********************************************************************** */
    @Override
    public void start(Stage arg0) throws Exception {
    }

}

0 个答案:

没有答案