无法使用正确的值填充表格单元格组合框

时间:2017-11-08 16:40:37

标签: java mysql

我有一个带有两个表的MySQl数据库; user和user_role。

表用户包含字段: (PK)int user_id      string user_name      字符串密码      string firstName      字符串LastName (FK)int role_id

表user_role包含字段: (PK)int role_id      string role_type

我有一个tableview,我想根据组合框表格单元格从用户表中编辑role_id。我需要组合框表格单元格包含role_type作为字符串名称,但返回role_id的字符串。

我有两个模型UserModel和RoleModel。 RoleModel包含从数据库中检索的role_id和role_type。 UserModel从用户表中检索所有字段,并在TableView中显示该字段。我想要实现的是一个表格单元格组合框,其中包含user_role表中的所有记录,当进行选择时,它将为用户更改存储在后端数据库中的值。如果需要实现所需的结果,我不确定如何将两个类UserModel和RoleModel合并在一起。或者有替代解决方案吗?

public class RoleModel {


    private final StringProperty roleId;
    private final StringProperty roleName;



    public RoleModel(String roleId, String roleName){
        this.roleId = new SimpleStringProperty(roleId);
        this.roleName = new SimpleStringProperty(roleName);
    }

    public String getId() {return roleId.get(); }
    public String getRoleName() { return roleName.get(); }
    public StringProperty roleIdProperty(){ return roleId; }
    public StringProperty roleNameProperty(){ return roleName; }
    public void setRoleId(String roleId){this.roleId.set(roleId);}
    public void setRoleName(String roleName){this.roleName.set(roleName);}
}

public class UserModel {

    private final StringProperty userId;
    private final StringProperty userName;
    private final StringProperty password;
    private final StringProperty roleName;
    private final StringProperty firstName;
    private final StringProperty lastName;

    public UserModel(String userId, String userName, String password, String roleName, String firstName, String lastName){

        this.userId = new SimpleStringProperty(userId);
        this.userName = new SimpleStringProperty(userName);
        this.password = new SimpleStringProperty(password);
        this.roleName = new SimpleStringProperty(roleName);
        this.firstName = new SimpleStringProperty(firstName);
        this.lastName = new SimpleStringProperty(lastName);
    }

    public String getUserId(){
        return userId.get();
    }

    public String getUserName(){
        return userName.get();
    }

    public String getPassword(){
        return password.get();
    }

    public String getRoleName(){
        return roleName.get();
    }

    public String getFirstName(){
        return firstName.get();
    }

    public String getLastName(){
        return lastName.get();
    }

    public void setUserId(String id){
        this.userId.set(id);
    }

    public void setUserName(String userName){
        this.userName.set(userName);
    }

    public void setPassword(String password){
        this.password.set(password);
    }

    public void setRoleName(String role){
        this.roleName.set(role);
    }

    public void setFirstName(String firstName){
        this.firstName.set(firstName);
    }

    public void setLastName(String lastName){
        this.lastName.set(lastName);
    }

    public StringProperty userIdProperty(){
        return userId;
    }

    public StringProperty userNameProperty(){
        return userName;
    }

    public StringProperty passwordProperty(){
        return password;
    }

    public StringProperty roleNameProperty(){
        return roleName;
    }

    public StringProperty firstNameProperty(){
        return firstName;
    }

    public StringProperty lastNameProperty(){
        return lastName;
    }
}

public class UserController implements Initializable{  //Initializable allows tagged FXML to be accessed

    //Create form variables
    @FXML
    private TextField userName;
    @FXML
    private TextField password;
    @FXML
    private ComboBox<RoleModel> role;
    @FXML
    private TextField firstName;
    @FXML
    private TextField lastName;

    @FXML
    private Button btnAddUser;

    //Create table variables using UserModel
    @FXML
    private TableView<UserModel> userTable;
    @FXML 
    private TableColumn<UserModel, String> idColumn;
    @FXML
    private TableColumn<UserModel, String> userNameColumn;
    @FXML
    private TableColumn<UserModel, String> passwordColumn;
    @FXML
    private TableColumn<UserModel, String> roleColumn;
    @FXML
    private TableColumn<UserModel, String> firstNameColumn;
    @FXML
    private TableColumn<UserModel, String> lastNameColumn;

    private DBConnection DBconnection; //Create a DBConnection object to access the database   


    private ObservableList<UserModel> userData; //Create array to store data from the user table
    private ObservableList<RoleModel> roleType;  //Create array to store data from the role table

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle){


        this.DBconnection = new DBConnection();
        try {
            setupCellValueFactories();
            loadUserData(); //Call method to load the user table when the window opens
            loadRoleOptions();
            populateRolesCombobox(); //Call method to load role type into the role combobox

            setupUserNameColumn();
            setupPasswordColumn();
            setupRoleColumn();
            setupFirstNameColumn();
            setupLastNameColumn();
            setTableEditable();
        } catch (SQLException error) {
            System.err.print(error);
        }

    }

    private void setupCellValueFactories(){
        this.idColumn.setCellValueFactory(new PropertyValueFactory<>("userId"));
        this.userNameColumn.setCellValueFactory(new PropertyValueFactory<>("userName"));
        this.passwordColumn.setCellValueFactory(new PropertyValueFactory<>("password"));
        this.roleColumn.setCellValueFactory(new PropertyValueFactory<>("roleName"));
        this.firstNameColumn.setCellValueFactory(new PropertyValueFactory<>("firstName"));
        this.lastNameColumn.setCellValueFactory(new PropertyValueFactory<>("lastName"));
    }

    @FXML
    private void addUser(ActionEvent event) {
        String SQL = "INSERT INTO user (user_name, password, first_name, last_name, role_id) VALUES (?,?,?,?,?)";

        try {
            Connection connection = DBConnection.getConnection();

            PreparedStatement statement = connection.prepareStatement(SQL);
            statement.setString(1, this.userName.getText());
            statement.setString(2, this.password.getText());
            statement.setString(3, this.firstName.getText());
            statement.setString(4, this.lastName.getText());
            statement.setString(5, this.role.getSelectionModel().getSelectedItem().getId());

            statement.execute();
            connection.close();

            this.userName.setText("");
            this.password.setText("");
            this.firstName.setText("");
            this.lastName.setText("");

            loadUserData();


        } catch (SQLException error) {
             System.err.print(error);
        }
    }

    @FXML
    private void deleteUser(){

        PreparedStatement statement;

         String SQL = "DELETE user \n" +
                      "FROM mpd_production.user \n" +
                      "WHERE user_id = ?";
        try{
            Connection connection = DBConnection.getConnection();  //Create a connection to the database
            statement = connection.prepareStatement(SQL);
            statement.setString(1, userTable.getSelectionModel().getSelectedItem().getUserId());

            statement.executeUpdate();

            connection.close();

            loadUserData();

        } catch (SQLException error){
            System.out.println(error);
        }
    }

    private void updateUser(String newValue, String columnName){
        String SQL = "";

        switch(columnName) {
            case "userName":
                SQL = "UPDATE user SET user_name = ? WHERE user_id = ?";
                break;
            case "password":
                SQL = "UPDATE user SET password = ? WHERE user_id = ?";
                break;
            case "role":
                SQL = "UPDATE user SET role_id = ? WHERE user_id = ?";
                break;
            case "firstName":
                SQL = "UPDATE user SET first_name = ? WHERE user_id = ?";
                break;
            case "lastName":
                SQL = "UPDATE user SET last_name = ? WHERE user_id = ?";
                break;
        }

        PreparedStatement statement;
        try{
            Connection connection = DBConnection.getConnection(); //Create a connection to the database
            statement = connection.prepareStatement(SQL);
            statement.setString(1, newValue);
            statement.setString(2, userTable.getSelectionModel().getSelectedItem().getUserId());

            statement.executeUpdate();

            connection.close();

            loadUserData();

        } catch (SQLException error){
            System.out.println(error);
        }  
    }

    private void setupUserNameColumn(){
        //sets the cell factory to use Editcell which will handle key press
        //and firing commit events
        this.userNameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        this.userNameColumn.setOnEditCommit(new EventHandler<CellEditEvent<UserModel, String>>(){
            @Override
            public void handle(CellEditEvent Event){
                updateUser(Event.getNewValue().toString(), "userName");
            }
        });

    }

    private void setupPasswordColumn(){
        //sets the cell factory to use Editcell which will handle key press
        //and firing commit events
        this.passwordColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        this.passwordColumn.setOnEditCommit(new EventHandler<CellEditEvent<UserModel, String>>(){
            @Override
            public void handle(CellEditEvent Event){
                updateUser(Event.getNewValue().toString(), "password");
            }
        });
    }

    private void setupRoleColumn(){
        //sets the cell factory to use Editcell which will handle key press
        //and firing commit events
        this.roleColumn.setCellFactory(ComboBoxTableCell.forTableColumn());
        this.roleColumn.setOnEditCommit(new EventHandler<CellEditEvent<UserModel, String>>(){
            @Override
            public void handle(CellEditEvent Event){
                updateUser(Event.getNewValue().toString(), "role");
                System.out.println(Event.getNewValue());
            }

        });

    }

    private void setupFirstNameColumn(){
        this.firstNameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        this.firstNameColumn.setOnEditCommit(new EventHandler<CellEditEvent<UserModel, String>>(){
            @Override
            public void handle(CellEditEvent Event){
                updateUser(Event.getNewValue().toString(), "firstName");
            }
        });
    }

    private void setupLastNameColumn(){
        this.lastNameColumn.setCellFactory(TextFieldTableCell.forTableColumn());
        this.lastNameColumn.setOnEditCommit(new EventHandler<CellEditEvent<UserModel, String>>(){
            @Override
            public void handle(CellEditEvent Event){
                updateUser(Event.getNewValue().toString(), "lastName");
            }
        });
    }

    //This method populates the role combobox
    public void populateRolesCombobox(){
            this.role.setItems(roleType); //Set the items of the combobox to the roleData
            this.role.setCellFactory(roleTypeFactory);
            this.role.setButtonCell(roleTypeFactory.call(null));
    }



    private void setTableEditable(){
        userTable.setEditable(true); //Allows the individual cells to be selected
        userTable.getSelectionModel().cellSelectionEnabledProperty().set(true); //When characters or numbers are pressed it will start the edit in the editable fields
        userTable.setOnKeyPressed(event -> {
            if(event.getCode().isLetterKey() || event.getCode().isDigitKey()){
                editFocusedCell();
            } else if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.TAB){
                userTable.getSelectionModel().selectNext();
                event.consume();
            } else if (event.getCode() == KeyCode.LEFT){
                selectPrevious();
                event.consume();
            }
        });
    }

    private void editFocusedCell(){
        final TablePosition<UserModel, ?> focusedCell = userTable.focusModelProperty().get().focusedCellProperty().get();
            userTable.edit(focusedCell.getRow(), focusedCell.getTableColumn());
    }

    private void selectPrevious(){
        if(userTable.getSelectionModel().isCellSelectionEnabled()){
            //in the cell selection mode, we have to wrap around, going from
            //right-to-left, and then wrapping to the end of the previous line
            TablePosition<UserModel, ?> pos = userTable.getFocusModel().getFocusedCell();
            if(pos.getColumn() - 1 >= 0){
                //go to previous row
                userTable.getSelectionModel().select(pos.getRow(), getTableColumn(pos.getTableColumn(), -1));
            } else if(pos.getRow() < userTable.getItems().size()) {
                //wrap to end of the previous row
                userTable.getSelectionModel().select(pos.getRow() - 1, userTable.getVisibleLeafColumn(userTable.getVisibleLeafColumns().size() - 1));
            } else {
                int focusIndex = userTable.getFocusModel().getFocusedIndex();
                if(focusIndex == - 1){
                    userTable.getSelectionModel().select(userTable.getItems().size() - 1);
                } else if(focusIndex > 0) {
                    userTable.getSelectionModel().select(focusIndex - 1);
                }
            }
        }

    }

    private TableColumn<UserModel, ?> getTableColumn(final TableColumn<UserModel, ?> column, int offset){
        int columnIndex = userTable.getVisibleLeafIndex(column);
        int newColumnIndex = columnIndex + offset;
        return userTable.getVisibleLeafColumn(newColumnIndex);
    }





    private void loadUserData()throws SQLException{

        String SQL = "SELECT user.user_id, user.user_name, user.password, user_role.role_name, user.first_name, user.last_name\n" +  //Create SQL query to pull data from user table
                     "FROM user_role\n" +
                     "INNER JOIN user ON user_role.role_id = user.role_id ";

        try {
            Connection connection = DBConnection.getConnection(); //Create a connection to the Database
            this.userData = FXCollections.observableArrayList(); //Generate array

            ResultSet resultSet = connection.createStatement().executeQuery(SQL); //Execute the SQL string and store that data in the results set object
            while (resultSet.next()){ //Loop through the data until the method next() can no longer be called
               this.userData.add(new UserModel(resultSet.getString(1),resultSet.getString(2),resultSet.getString(3), resultSet.getString(4), resultSet.getString(5), resultSet.getString(6)));
            }

            connection.close();

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

        this.userTable.setItems(this.userData);
    }

    private void loadRoleOptions(){

        String SQL = "SELECT role_id, role_name \n" +  //Generate SQL query to pull related data
                     "FROM mpd_production.user_role;"; 

        try {
            Connection connection = DBConnection.getConnection();  //Create a connection to the database
            this.roleType = FXCollections.observableArrayList();
            ResultSet resultSet = connection.createStatement().executeQuery(SQL); //Execute the SQL string and store that data in the results set object
            while (resultSet.next()){ //Loop through the data until the method next() can no longer be called
                this.roleType.add(new RoleModel(resultSet.getString("role_id"), resultSet.getString("role_name")));  //Store role_id and role_name into the roleData array
            }
            connection.close(); //Finally, close the connection

        } catch (SQLException error) {
            System.out.println(error);
        }
    }

    Callback<ListView<RoleModel>, ListCell<RoleModel>> roleTypeFactory = listView -> new ListCell<RoleModel>(){
        @Override
        protected void updateItem(RoleModel item, boolean empty){
            super.updateItem(item, empty);
            setText(empty ? "" : item.getRoleName());
        }
    };
}

1 个答案:

答案 0 :(得分:0)

看起来UserModel#role应该是ObservableValue<RoleModel>roleColumn应该是TableColumn<UserModel, RoleModel>类型。

来自documentation

  

public ObjectProperty<StringConverter<T>> converterProperty()

     

将用户输入的输入(当ComboBox可编辑时)转换为对象   类型为T,这样可以通过value属性检索输入。

StringConverter#fromString仅在将文本输入可编辑ComboBox时使用,以选择与输入文本匹配的值。它不能用于在此上下文中将角色的字符串值自动转换为RoleModel对象。这就是您获得ClassCastException的原因,因为它试图将字符串值直接转换为RoleModel

此外,ComboBoxTableCell.forTableColumn使用TableCells<S, T>类型StringConverter返回一个单元格工厂,以创建ObservableList类型的<T> 。 因此,使用返回的单元工厂的TableColumn的第二个参数化类型必须与字符串转换器的类型匹配。

上面的代码试图填充TableColumn<UserModel, String> TableCells类型<UserModel, RoleModel>,然后用字符串数据填充TableCells