JavaFX: Create a dynamic tableview with generic types
Asked Answered
B

1

3

So, first of all, my code is based on the accepted answer in this thread.

I'm trying to create a tableview from a database, and this tableview should be populated dynamically based on what data the user asks for. While that's working so far, my problem is that all values gathered from the database are interpreted as strings in java, but I need their actual values.

The reason for this is that the built-in sorting mechanism of the javafx tableview sorts all numbers as strings because their type is converted to string when populating the table.

Example: Values 921, 200, 110, 1, 2011, 1299 would be sorted as (using integer datatype) 1, 110, 200, 921, 1299, 2011 while it would be sorted as 1, 110, 1299, 200, 2011, 921 using string datatype.

I'm quite new to generics and java in general, and hope someone here might be able to help me out.

Basically: whenever I read a value from the database, I need to insert the value in the tableview with its actual datatype, rather than it being converted to string.

Begorra answered 23/3, 2017 at 8:22 Comment(0)
B
5

This should work if you use ResultSet.getObject(index) to populate the table. The JDBC driver will return an appropriate object type, according to standard mappings defined in the JDBC specification (e.g. an int column will map to a java.lang.Integer, etc).

I don't particularly like the code you linked: it produces a lot of warnings about type safety, to which you should pay attention. I would use something like this (caveat: not tested):

Data wrapper class:

public class DataResult {

    private final List<String> columnNames ;
    private final List<List<Object>> data ;

    public DataResult(List<String> columnNames, List<List<Object>> data) {
        this.columnNames = columnNames ;
        this.data = data ;
    }

    public int getNumColumns() {
        return columnNames.size();
    }

    public String getColumnName(int index) {
        return columnNames.get(index);
    }

    public int getNumRows() {
        return data.size();
    }

    public Object getData(int column, int row) {
        return data.get(row).get(column);
    }

    public List<List<Object>> getData() {
        return data ;
    }
}

Database accessor class:

public class DAO {

    private Connection conn ;


    public DAO() {
        // initialize connection...
    }

    public DataResult getAllData() throws SQLException {

        List<List<Object>> data = new ArrayList<>();
        List<String> columnNames = new ArrayList<>();

        try (
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery("select * from some_table")) {


            int columnCount = rs.getMetaData().getColumnCount();

            for (int i = 1 ; i <= columnCount ; i++) {
                columnNames.add(rs.getMetaData().getColumnName(i));
            }

            while (rs.next()) {
                List<Object> row = new ArrayList<>();
                for (int i = 1 ; i <= columnCount ; i++) {
                    row.add(rs.getObject(i));
                }
                data.add(row);
            }
        }

        return new DataResult(columnNames, data);
    }
}

GUI code:

TableView<List<Object>> table = new TableView<>();
DAO dao = new DAO();
DataResult data = dao.getAllData();

for (int i = 0 ; i < data.getNumColumns() ; i++) {
    TableColumn<List<Object>, Object> column = new TableColumn<>(data.getColumnName(i));
    int columnIndex = i ;
    column.setCellValueFactory(cellData -> 
        new SimpleObjectProperty<>(cellData.getValue().get(columnIndex)));
    table.getColumns().add(column);
}

table.getItems().setAll(data.getData());

Using this version, the data provided to the table contains objects of the appropriate type for the columns - not necessarily strings. So, for example, if a database column is defined with (SQL) type int, then the table view column will contain java.lang.Integer instances, and the sorting will be according to the implementation of Integer.compareTo(...) (i.e. in proper numeric order).

Bankbook answered 23/3, 2017 at 14:41 Comment(3)
Thanks a lot for this, this was exactly what I was looking for. It's working like a charm and it makes a lot more sense than the code I used before. I'm trying to follow the mvc design pattern, and I'm still new to how it works. How would you suggest I categorize this code?Wean
This is an implementation (loosely) of the DAO pattern. In MVC you would make the DAO part of the model, and the controller would refer to the model to get the data (the model delegating to the DAO).Bankbook
Okay, that was what I thought. Allright, well thanks again!Wean

© 2022 - 2024 — McMap. All rights reserved.