@delphi08

Как правильно создать модель данных для TableView в JavaFX?

Создана программа, выводящая в TableView данные из SQL-запроса к Oracle (12c).
Проблема в том, что некоторые данные в TableView выводятся, некоторые - нет.
Код программы:

//1. Класс Controller

package sample;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.AnchorPane;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.sql.*;


import java.util.Formatter;

public class Controller extends Const{


    @FXML
    private ResourceBundle resources;

    @FXML
    private URL location;

    @FXML
    private AnchorPane podlojkaInt;

    @FXML
    private Button buttonClick;


    @FXML
    private TableColumn<DataModelSQL, String> columnOne;

    @FXML
    private TableColumn<DataModelSQL, String> columnTwo;

    @FXML
    private TableColumn<DataModelSQL, String> columnThree;

    @FXML
    private TableColumn<DataModelSQL, String> columnFour;


    @FXML
    private TableColumn<DataModelSQL, String> columnFive;

    @FXML
    private TableColumn<DataModelSQL, String> columnSix;

    @FXML
    private TableColumn<DataModelSQL, String> columnSeven;


    @FXML
    private TableView<DataModelSQL> tableShow;


    @FXML
    void initialize() {


        ObservableList<DataModelSQL> list = FXCollections.observableArrayList();
        tableShow.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        tableShow.getSelectionModel().setCellSelectionEnabled(true);



        buttonClick.setOnAction(event -> {

            DatabBaseHandler connect = new DatabBaseHandler();


            String sql = "SELECT * FROM TABLE.NAME WHERE ID_COLUMN1 = 12 AND ID_COLUMN2 = 1234";

            try {
                Statement statement = connect.getDbConnection().createStatement();
                ResultSet resultSet = statement.executeQuery(sql);


                while (resultSet.next()) {


                    String column3 = resultSet.getString(3);
                    System.out.println(column3);


                    list.add(new DataModelSQL(resultSet.getString(1),resultSet.getString(2),
                            resultSet.getString(3),resultSet.getString(4),
                            resultSet.getString(5),resultSet.getString(6),
                            resultSet.getString(7)));

                    columnOne.setCellValueFactory(new PropertyValueFactory<DataModelSQL, String>("idV"));
                    columnTwo.setCellValueFactory(new PropertyValueFactory<DataModelSQL, String>("idS"));
                    columnThree.setCellValueFactory(new PropertyValueFactory<DataModelSQL, String>("val"));
                    columnFour.setCellValueFactory(new PropertyValueFactory<DataModelSQL, String>("idUser"));
                    columnFive.setCellValueFactory(new PropertyValueFactory<DataModelSQL, String>("idVParent"));
                    columnSix.setCellValueFactory(new PropertyValueFactory<DataModelSQL, String>("dateAdd"));
                    columnSeven.setCellValueFactory(new PropertyValueFactory<DataModelSQL, String>("visible"));


                    tableShow.setItems(list);



                }
                resultSet.close();
                statement.close();

            } catch (SQLException | ClassNotFoundException e) {
                e.printStackTrace();
                System.out.println(e.getMessage());
            }
        });

    }
}

//2. Класс DataModelSQL

package sample;

import javafx.beans.property.*;


//это класс для модели данных, получаемых из БД
public class DataModelSQL {


    private SimpleStringProperty idV;
    private SimpleStringProperty idS;
    private SimpleStringProperty val;
    private SimpleStringProperty idUser;
    private SimpleStringProperty idVParent;
    private SimpleStringProperty dateAdd;
    private SimpleStringProperty visible;



    public DataModelSQL(String idV, String idS, String val, String idUser,
                        String idVParent, String dateAdd, String visible)
    {
        this.idV = new SimpleStringProperty(idV);
        this.idS = new SimpleStringProperty(idS);
        this.val = new SimpleStringProperty(val);
        this.idUser = new SimpleStringProperty(idUser);
        this.idVParent = new SimpleStringProperty(idVParent);
        this.dateAdd = new SimpleStringProperty(dateAdd);
        this.visible = new SimpleStringProperty(visible);
    }


    public String getIdV()
    { return idV.get();}
    public void setIdV(String value)
    { idV.set(value);}

    public String getIdS()
    { return idSlv.get();}
    public void setIdS(String value)
    { idSlv.set(value);}

    public String getVal()
    { return val.get();}
    public void setVal(String value)
    { val.set(value);}

    public String getIdUser()
    { return idUser.get();}
    public void setIdUser(String value)
    { idUser.set(value);}

    public String getIdVParent()
    { return idVParent.get();}
    public void setIdVParent(String value)
    { idVParent.set(value);}

    public String getDateAdd()
    { return dateAdd.get();}
    public void setDateAdd(String value)
    { dateAdd.set(value);}

    public String getVisible()
    { return visible.get();}
    public void setVisible(String value)
    { visible.set(value);}

}


TableView выводит результаты колонок: 2, 4, 6, 7, не выводит - 1, 3, 5.
Типы данных в колонках:
1 - number
2 - number
3 - varchar2(2000)
4 - number
5 - number
6 - timestamp
7 - number

По тем колонкам, в которых данные не выводятся, вылетает ошибка, пример:
Can not retrieve property 'idVParent' in PropertyValueFactory: javafx.scene.control.cell.PropertyValueFactory@b0e3501 with provided class type: class sample.DataModelSQL
java.lang.IllegalStateException: Cannot read from unreadable property idVParent

Не совсем понятно, что имеется в виду под "не читаемым свойством".
Тем не менее, полагаю, дело в модели данных и ее работе с типами данных, так как
с помощью тестового кода:

String column3 = resultSet.getString(3);
System.out.println(column3);


в цикле while, удавалось в консоль вывести значение колонки №3, которую не выводит TableView.

Поэтому, в итоге вопрос: что неверно прописано в моей модели данных?
Дело в типах данных, прописанных в классе-модели DataModelSQL или в неверном обращении к ней из класса Controller?

Также не откажусь от замечаний по общему написанию кода.
  • Вопрос задан
  • 874 просмотра
Пригласить эксперта
Ответы на вопрос 1
jamakasi666
@jamakasi666
Просто IT'шник.
  1. Не усложняйте себе жизнь и не используйте FXML, описывайте формы в коде
  2. в DataModelSQL надо еще добавить методы типа
    public StringProperty valProperty() { return val; }

    Смотрите справку

  3. работать с данными в контроллере не надо, особенно если операция может быть долгой. Выносите работу с БД отдельно, даже в отдельный поток. а в контроллере прилипите buttonClick.setOnAction(event -> {meDBWorker.getMyData();}
  4. свойства columnOne.setCellValueFactory.. вы задаете в цикле, не надо так, задайте их единожды при создание ui таблицы. Опять же отчасти у вас это скорее всего изза использования fxml, отсюда и не понимание
  5. свой list при запросе из БД вы не очищаете и каждый раз пихаете в него одно и тоже. Кроме того tableShow.setItems(list) вы опять же делаете в цикле и опять же это надо сделать единожды при создании UI
  6. в DataModelSQL все поля сделайте final

Ну и еще, существует гора библиотек для работы с таблицами в javafx в т.ч. с мапингом к БД. В чистом виде на чистом jfx придется очень многое делать руками, начиная от некоторых видов ячеек для некоторых данных, заканчивания банальными редактированиями\обновлениями и т.д. Аналогично есть целый пласт технологий и библиотек для работы с БД, начиная от простых и заканчивания афигеть мощными, погуглите на тему ORM
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы