Tableview 在编辑时更新数据库

M.v*_*aal 3 database javafx tableview

所以我想要发生的事情是让 tableview 在编辑后更新数据库中的数据。我想在这里使用 SetOnEditCommit 方法。单元格编辑确实有效,但它永远不会更新,也没有错误。首先,如果这种方法实际上有效(可能不是),我有点无能为力,因为很难找到这个特定事物的一些来源。我发现的来源并没有真正的帮助。因此,如果有人知道它为什么不更新,或者在这里提供替代选项,那就太好了。

提到的部分:

    columnType.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<UserDetails, String>>() {
            @Override
            public void handle(TableColumn.CellEditEvent<UserDetails, String> event) {
              updataData();
            }
        });

        tableview.setItems(null);
        tableview.setItems(data);

    }


    public void updataData() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection("jdbc:mysql://37.128.148.113:3306/FYS", "FYS", "Kcj8g87~");
            Statement con = connection.createStatement();
            //connection
            TablePosition pos = tableview.getSelectionModel().getSelectedCells().get(0);
            int row = pos.getRow();
            TableColumn col = pos.getTableColumn();
             String data1 = (String) col.getCellObservableValue(row).getValue();
            //cell
            UserDetails row1 = tableview.getSelectionModel().getSelectedItem();
            c1 = row1.getId();
            //row
            //tableview variables
            con.execute("UPDATE gevonden_bagage SET  type = 'data1' WHERE koffer_id = 'c1' ");
            //Query       
        } catch (SQLException ex) {
            System.err.println("Error" + ex);
        }
    }
//get connection, get celldata, get id data from first row, update cell with selected id
Run Code Online (Sandbox Code Playgroud)

完整的控制器类:

package simple;

import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TablePosition;

import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.cell.TextFieldTableCell;

/**
 *
 * @author admin
 */
public class FXMLUserController extends SimpleController implements Initializable {

    @FXML
    public TableView<UserDetails> tableview;
    @FXML
    public TableColumn<UserDetails, String> columnId;
    @FXML
    public TableColumn<UserDetails, String> columnType;
    @FXML
    public TableColumn<UserDetails, String> columnKleur;
    @FXML
    public TableColumn<UserDetails, String> columnLuchthaven;
    @FXML
    public TableColumn<UserDetails, String> columnKenmerken;
    @FXML
    public TableColumn<UserDetails, String> columnStatus;
    @FXML
    public TableColumn<UserDetails, String> columnDatum;
    @FXML
    private Button btnLoad;
    //declare observable list for database data
    private ObservableList<UserDetails> data;
    private DbConnection dc;
    String c1;

    @FXML

//strings for getRow method
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        dc = new DbConnection();
        loadDataFromDatabase();
    }

    @FXML
    public void loadDataFromDatabase() {
        try {
            Connection conn = dc.Connect();
            data = FXCollections.observableArrayList();
            // Execute query and store result in a resultset
            ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM gevonden_bagage");
            while (rs.next()) {
                //get strings
                data.add(new UserDetails(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5),
                        rs.getString(6), rs.getString(7)));
            }

        } catch (SQLException ex) {
            System.err.println("Error" + ex);
        }

        //Set cell values to tableview.
        tableview.setEditable(true);
        tableview.getSelectionModel().setCellSelectionEnabled(true);

        columnType.setCellFactory(TextFieldTableCell.forTableColumn());
        columnKleur.setCellFactory(TextFieldTableCell.forTableColumn());
        columnLuchthaven.setCellFactory(TextFieldTableCell.forTableColumn());
        columnKenmerken.setCellFactory(TextFieldTableCell.forTableColumn());
        columnStatus.setCellFactory(TextFieldTableCell.forTableColumn());
        columnDatum.setCellFactory(TextFieldTableCell.forTableColumn());
//makes columns editable
        columnId.setCellValueFactory(new PropertyValueFactory<>("id"));
        columnType.setCellValueFactory(new PropertyValueFactory<>("type"));
        columnKleur.setCellValueFactory(new PropertyValueFactory<>("kleur"));
        columnLuchthaven.setCellValueFactory(new PropertyValueFactory<>("luchthaven"));
        columnKenmerken.setCellValueFactory(new PropertyValueFactory<>("kenmerken"));
        columnStatus.setCellValueFactory(new PropertyValueFactory<>("status"));
        columnDatum.setCellValueFactory(new PropertyValueFactory<>("datum"));

    columnType.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<UserDetails, String>>() {
            @Override
            public void handle(TableColumn.CellEditEvent<UserDetails, String> event) {
              updataData();
            }
        });

        tableview.setItems(null);
        tableview.setItems(data);

    }


    public void updataData() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection("jdbc:mysql://37.128.148.113:3306/FYS", "FYS", "Kcj8g87~");
            Statement con = connection.createStatement();
            //connection
            TablePosition pos = tableview.getSelectionModel().getSelectedCells().get(0);
            int row = pos.getRow();
            TableColumn col = pos.getTableColumn();
             String data1 = (String) col.getCellObservableValue(row).getValue();
            //cell
            UserDetails row1 = tableview.getSelectionModel().getSelectedItem();
            c1 = row1.getId();
            //row
            //tableview variables
            con.execute("UPDATE gevonden_bagage SET  type = 'data1' WHERE koffer_id = 'c1' ");
            //Query       
        } catch (SQLException ex) {
            System.err.println("Error" + ex);
        }
    }
//get connection, get celldata, get id data from first row, update cell with selected id
    @FXML
    public void getRow() {

        TablePosition pos = tableview.getSelectionModel().getSelectedCells().get(0);
        int row = pos.getRow();
        TableColumn col = pos.getTableColumn();
// this gives the value in the selected cell:
        String data1 = (String) col.getCellObservableValue(row).getValue();
        System.out.println(data1);
//CURRENTLY UNUSED METHOD
    }

}
Run Code Online (Sandbox Code Playgroud)

模型类:

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
 *
 * @author admin
 */
public class UserDetails {

    private final StringProperty id;
    private final StringProperty type;
    private final StringProperty kleur;
    private final StringProperty luchthaven;
    private final StringProperty kenmerken;
    private final StringProperty status;
    private final StringProperty datum;

    //Default constructor
    public UserDetails(String id, String type, String kleur, String luchthaven, String kenmerken, String status, String datum) {
        this.id = new SimpleStringProperty(id);
        this.type = new SimpleStringProperty(type);
        this.kleur = new SimpleStringProperty(kleur);
        this.luchthaven = new SimpleStringProperty(luchthaven);
        this.kenmerken = new SimpleStringProperty(kenmerken);
        this.status = new SimpleStringProperty(status);
        this.datum = new SimpleStringProperty(datum);

    }

    //getters
    public String getId() {
        return id.get();
    }

    public String getType() {
        return type.get();
    }

    public String getKleur() {
        return kleur.get();
    }

    public String getLuchthaven() {
        return luchthaven.get();
    }

    public String getKenmerken() {
        return kenmerken.get();
    }

    public String getStatus() {
        return status.get();
    }

    public String getDatum() {
        return datum.get();
    }

    //setters
    public void setId(String value) {
        id.set(value);
    }

    public void setType(String value) {
        type.set(value);
    }

    public void setKleur(String value) {
        kleur.set(value);
    }

    public void setLuchthaven(String value) {
        luchthaven.set(value);
    }

    public void setKenmerken(String value) {
        kenmerken.set(value);
    }

    public void setStatus(String value) {
        status.set(value);
    }

    public void setDatum(String value) {
        datum.set(value);
    }

    //property values
    public StringProperty idProperty() {
        return id;
    }

    public StringProperty typeProperty() {
        return type;
    }

    public StringProperty kleurProperty() {
        return kleur;
    }

    public StringProperty luchthavenProperty() {
        return luchthaven;
    }

    public StringProperty kenmerkenProperty() {
        return kenmerken;
    }

    public StringProperty statusProperty() {
        return status;
    }

    public StringProperty datumProperty() {
        return datum;
    }
}
Run Code Online (Sandbox Code Playgroud)

Jam*_*s_D 5

TableView文档

默认情况下,TableColumn 编辑提交处理程序是非空的,默认处理程序会尝试覆盖当前正在编辑的行中项目的属性值。当 Cell.commitEdit(Object) 方法传入新值时,它能够做到这一点,并且通过触发的 CellEditEvent 将其传递给编辑提交处理程序。只需调用 TableColumn.CellEditEvent.getNewValue() 即可检索此值。

请务必注意,如果您使用自己的 EventHandler 调用 TableColumn.setOnEditCommit(javafx.event.EventHandler),那么您将删除默认处理程序。除非您随后处理对属性(或相关数据源)的写回,否则不会发生任何事情。

所以问题是,通过设置onEditCommiton columnType,您删除了实际typePropertyUserDetails实例中更新的默认处理程序。最后

String data1 = (String) col.getCellObservableValue(row).getValue();
Run Code Online (Sandbox Code Playgroud)

给出旧值,您对数据库的更新不会改变任何东西。

此外,您在创建 SQL 语句的方式上有错误。您将WHERE子句中的 id设为文字值'c1'(而不是包含在变量中的值c1,类似地将 的值设置type为文字值'data1',而不是变量中的值data1

这是一个修复程序,以及一些代码的简化和一些避免SQL 注入攻击的更好做法:

columnType.setOnEditCommit(event -> {
    UserDetails user = event.getRowValue();
    user.setType(event.getNewValue());
    updateData("type", event.getNewValue(), user.getId());
});
Run Code Online (Sandbox Code Playgroud)

进而

private void updateData(String column, String newValue, String id) {

    // btw it is way better to keep the connection open while the app is running,
    // and just close it when the app shuts down....

    // the following "try with resources" at least makes sure things are closed:

    try (
        Connection connection = DriverManager.getConnection("jdbc:mysql://37.128.148.113:3306/FYS", "FYS", "Kcj8g87~");
        PreparedStatement stmt = connection.prepareStatement("UPDATE gevonden_bagage SET "+column+" = ? WHERE koffer_id = ? ");
    ) {

        stmt.setString(1, newValue);
        stmt.setString(2, id);
        stmt.execute();
    } catch (SQLException ex) {
        System.err.println("Error");
        // if anything goes wrong, you will need the stack trace:
        ex.printStackTrace(System.err);
    }
}
Run Code Online (Sandbox Code Playgroud)