Обновлять TableView после удаления записи из БД

236
23 декабря 2017, 05:20

Есть метод, который удаляет из БД выбранную в TableView запись. Запись из БД нормально удаляется, а как обновить TableView? В TableView остается запись, пока не перезапустить приложение.

public class MainController {
    @FXML
    private ComboBox categoryComboBox;
    @FXML
    private TableView<Phone> phonesTable;
    @FXML
    private TableColumn<Phone, Integer> idColumn;
    @FXML
    private TableColumn<Phone, String> modelColumn;
    @FXML
    private TableColumn<Phone, Integer> priceColumn;
    @FXML
    private TableColumn<Phone, String> categoryColumn;
    @FXML
    private TableColumn<Phone, String> descriptionColumn;
    @FXML
    private TableColumn<Phone, String> producerColumn;
    @FXML
    private TableColumn<Phone, Integer> statusColumn;
    //Главная сцена
    private Stage mainStage;
    //Сцена редактирования информации
    private Stage editStage;
    //Загрузчик для сцен редактирования и добавления
    private FXMLLoader fxmlLoader = new FXMLLoader();
    //Parent для сцены редактирования
    Parent fxmlEdit;
    //Контроллер сцены редактирования
    EditController editController;
    //Телефоны
    private Phones phonesList = new Phones();
    //Категории
    private Categories categoriesList = new Categories();
    //Фильтруемый список. Нужен для фильтрации списка телефонов, когда в выпадающем списке будет выбираться определенная категория
    private FilteredList<Phone> filteredList = new FilteredList<Phone>(phonesList.getPhoneList(), phone -> true);
    //Метод устанавливает подмостки для главного контроллера
    public void setMainStage(Stage mainStage) {
        this.mainStage = mainStage;
    }
    //Метод инициализации
    public void initialize() throws SQLException, IOException {
        fillPhonesTable();
        fillCategoryComboBox();
        //Выводим в колонки TableView данные из списка
        idColumn.setCellValueFactory(new PropertyValueFactory<Phone, Integer>("id"));
        modelColumn.setCellValueFactory(new PropertyValueFactory<Phone, String>("model"));
        priceColumn.setCellValueFactory(new PropertyValueFactory<Phone, Integer>("price"));
        categoryColumn.setCellValueFactory(new PropertyValueFactory<Phone, String>("category"));
        descriptionColumn.setCellValueFactory(new PropertyValueFactory<Phone, String>("description"));
        producerColumn.setCellValueFactory(new PropertyValueFactory<Phone, String>("producer"));
        statusColumn.setCellValueFactory(new PropertyValueFactory<Phone, Integer>("status"));
        comboBoxFilter(categoryComboBox);
        //Сортируемый список, чтобы при нажатии на колонку в TableView данные сортировались
        SortedList<Phone> sortedList = new SortedList<Phone>(filteredList);
        //Выполняет сортировку данных в TableView при нажатии на заголовок колонки в TavleView
        sortedList.comparatorProperty().bind(phonesTable.comparatorProperty());
        //Выводим отсортированные и отфильтрованные данные в TableView
        phonesTable.setItems(sortedList);
        //Загружаем сцену редактирования
        editSceneLoader();
    }
    //Данный метод заполняет выпадающий список categoryComboBox названиями категорий из таблицы БД
    private void fillCategoryComboBox() throws SQLException, IOException {
        //Заполняем список названиями категорий
        categoriesList.fillCategoryList();
        //Устанавливаем для ComboBox значения из списка, который получили на предыдущем этапе.
        categoryComboBox.setItems(categoriesList.getCategoryList());
    }
    private void fillPhonesTable() throws SQLException, IOException {
        //Заполняем список phonesList телефонами
        phonesList.fillPhoneList();
        //При двойном клике на запись открываем окно для редактирования информации
        phonesTable.setOnMouseClicked(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                if (event.getClickCount() == 2) {
                    //Устанавливаем методику. Т.е. передаем в сцену редактирования данные о выбранной модели телефона
                    editController.setPhone((Phone) phonesTable.getSelectionModel().getSelectedItem());
                    //Вызываем метод, для отображения модального окна
                    editSceneShow();
                }
            }
        });
    }
    //Метод фильтрует записи в TableView при выборе категории в ComboBox
    private void comboBoxFilter(ComboBox comboBox) {
        comboBox.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                filteredList.setPredicate(phone -> {
                    if (comboBox.getValue() == null) {
                        return true;
                    }
                    String filter = comboBox.getValue().toString().toLowerCase();
                    if (phone.getCategory().toLowerCase().equals(filter)) {
                        return true;
                    }
                    return false;
                });
            }
        });
    }
    public void onDeleteClick(ActionEvent actionEvent) throws SQLException, IOException {
        try (Connection connection = DBConnection.getConnection()) {
            //Составляем подготовленный запрос на удаление записи из таблицы
            String deleteQuery = "DELETE FROM phones WHERE id = ?";
            //Подготовленный запрос
            PreparedStatement statement = connection.prepareStatement(deleteQuery);
            //Получаем выбранную в TableView запись (т.е. объект типа Phone) и получаем значения поля id через геттер getID()
            statement.setInt(1, phonesTable.getSelectionModel().getSelectedItem().getId());
            //Выполняем сам запрос
            statement.executeUpdate();
        }
    }
}

Сделал так. Есть ли способ лучше?

public void onDeleteClick(ActionEvent actionEvent) throws SQLException, IOException {
        try (Connection connection = DBConnection.getConnection()) {
            //Составляем подготовленный запрос на удаление записи из таблицы
            String deleteQuery = "DELETE FROM phones WHERE id = ?";
            //Подготовленный запрос
            PreparedStatement statement = connection.prepareStatement(deleteQuery);
            //Получаем выбранную в TableView запись (т.е. объект типа Phone) и получаем значения поля id через геттер getID()
            statement.setInt(1, phonesTable.getSelectionModel().getSelectedItem().getId());
            //Выполняем сам запрос
            statement.executeUpdate();
            //Удаляем из списка phonesList удаляемый из БД элемент.
            // Т.е. узнаем индекс выбранной записи из TableView и удаляем элемент с таким id в списке phonesList
            phonesList.getPhoneList().remove(phonesTable.getSelectionModel().getSelectedIndex());
            //Фильтруемый список. Нужен для фильтрации списка телефонов, когда в выпадающем списке будет выбираться определенная категория
            FilteredList<Phone> filteredList = new FilteredList<Phone>(phonesList.getPhoneList(), phone -> true);
            //Сортируемый список, чтобы при нажатии на колонку в TableView данные сортировались
            SortedList<Phone> sortedList = new SortedList<Phone>(filteredList);
            //Выполняет сортировку данных в TableView при нажатии на заголовок колонки в TavleView
            sortedList.comparatorProperty().bind(phonesTable.comparatorProperty());
            //Выводим отсортированные и отфильтрованные данные в TableView
            phonesTable.setItems(sortedList);
        }
    }

Вот такая ошибка

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1787) at javafx.fxml/javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1670) at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49) at javafx.base/javafx.event.Event.fireEvent(Event.java:198) at javafx.graphics/javafx.scene.Node.fireEvent(Node.java:8863) at javafx.controls/javafx.scene.control.Button.fire(Button.java:200) at javafx.controls/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:206) at javafx.controls/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274) at javafx.base/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218) at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80) at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) at javafx.base/javafx.event.Event.fireEvent(Event.java:198) at javafx.graphics/javafx.scene.Scene$MouseHandler.process(Scene.java:3876) at javafx.graphics/javafx.scene.Scene$MouseHandler.access$1300(Scene.java:3604) at javafx.graphics/javafx.scene.Scene.processMouseEvent(Scene.java:1874) at javafx.graphics/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2613) at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:397) at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295) at java.base/java.security.AccessController.doPrivileged(Native Method) at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:434) at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:433) at javafx.graphics/com.sun.glass.ui.View.handleMouseEvent(View.java:556) at javafx.graphics/com.sun.glass.ui.View.notifyMouse(View.java:942) at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:175) at java.base/java.lang.Thread.run(Thread.java:844) Caused by: java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at com.sun.javafx.reflect.Trampoline.invoke(MethodUtil.java:76) at jdk.internal.reflect.GeneratedMethodAccessor2.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:564) at javafx.base/com.sun.javafx.reflect.MethodUtil.invoke(MethodUtil.java:275) at javafx.fxml/com.sun.javafx.fxml.MethodHelper.invoke(MethodHelper.java:83) at javafx.fxml/javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1782) ... 47 more Caused by: java.lang.UnsupportedOperationException at java.base/java.util.AbstractList.remove(AbstractList.java:167) at java.base/java.util.AbstractList$Itr.remove(AbstractList.java:387) at java.base/java.util.AbstractCollection.remove(AbstractCollection.java:299) at phonesapp.controllers.MainController.onDeleteClick(MainController.java:249) ... 58 more

На строке

phonesTable.getItems().remove(phonesTable.getSelectionModel().getSelectedItem());

Класс Phones

public class Phones {
    private ObservableList<Phone> phoneList = FXCollections.observableArrayList();
    public ObservableList<Phone> getPhoneList() {
        return phoneList;
    }
    public void fillPhoneList() throws SQLException, IOException {
        try (Connection connection = DBConnection.getConnection()) {
            Statement statement = connection.createStatement();
            String query = "SELECT * FROM phones LEFT OUTER JOIN category ON phones.categoryID = category.id LEFT OUTER JOIN producer ON phones.producerID = producer.id";
            try (ResultSet resultSet = statement.executeQuery(query)) {
                while (resultSet.next()) {
                    int id = resultSet.getInt("id");
                    String model = resultSet.getString("model");
                    int price = resultSet.getInt("price");
                    String category = resultSet.getString("category");
                    String description = resultSet.getString("description");
                    String producer = resultSet.getString("producer");
                    int status = resultSet.getInt("status");
                    phoneList.add(new Phone(id, model, price, category, description, producer, status));
                }
            }
        }
    }
}
READ ALSO
Передача файла TelegramBot через POST. Как?

Передача файла TelegramBot через POST. Как?

Для передачи сообщения используется такой запрос:

253
Как лучше хранить картинки приложения в drawable или assets

Как лучше хранить картинки приложения в drawable или assets

Приложение имеет сложный дизайн и по этому было решено делать прорисовку на surfaceView, то есть почти нет никаких xml файлов, все отрисовывается...

239
Cannot acces java.lang.String

Cannot acces java.lang.String

Почему в записи кода thisname = name; есть ошибка Cannot acces java

232
Как создать свой конвертер в Retrofit?

Как создать свой конвертер в Retrofit?

Как создать свой конвертер в Retrofit?

216