JavaFX + Hibernate:动态更改Model-GUI绑定

时间:2018-09-23 18:11:51

标签: java hibernate javafx orm

我刚刚开始使用Hibernate和JavaFX。在我的测试应用程序中,用户可以输入Person的联系方式(姓名,地址,街道,邮政编码,城市)并将其保存到数据库中。 TextFields下面的TableView应该显示现有数据:

Screenshot of the test program

目前,我一直坚持将输入文本字段连接到模型类。使用JavaFX的StringPropertyIntegerProperty对象进行映射本身是可行的,但是我认为我做错了方法。

Person对象保存到数据库后,我想清除输入字段,以便用户可以创建新的Person。为此,我必须删除所有Model-GUI映射,创建一个新对象,然后重新映射所有内容。另外,如果用户选择tableView中的现有条目之一,那么我想用所选对象填充输入字段,以便用户可以更新条目。这也将需要重新进行所有属性映射。这听起来是错误的,所以我认为必须有一个更好的解决方案。

我考虑过仅在用户单击保存按钮然后执行所有StringProperty映射时创建一个Person对象,但这也是很多开销。我也可以使用普通的字符串,然后省略Property-class。

您对我有什么建议或资源吗?

这是控制器类:

package test.gui;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.util.converter.NumberStringConverter;
import org.hibernate.Session;
import test.models.Person;

import javax.persistence.TypedQuery;
import java.net.URL;
import java.util.List;
import java.util.ResourceBundle;

import static test.Database.getFactory;

public class MainWindowController implements Initializable {

    @FXML
    private TextField firstName;

    @FXML
    private TextField lastName;

    @FXML
    private TextField street;

    @FXML
    private TextField zip;

    @FXML
    private TextField city;

    @FXML
    private TableView<Person> tableView;

    @FXML
    private TableColumn<Person, String> tblFirstName;

    @FXML
    private TableColumn<Person, String> tblLastName;

    @FXML
    private TableColumn<Person, String> tblStreet;

    @FXML
    private TableColumn<Person, Integer> tblZip;

    @FXML
    private TableColumn<Person, String> tblCity;

    private Person currentPerson = null;

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

        // Map table columns to Person model
        tblFirstName.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
        tblLastName.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());
        tblStreet.setCellValueFactory(cellData -> cellData.getValue().streetProperty());
        tblZip.setCellValueFactory(cellData -> cellData.getValue().zipProperty().asObject());
        tblCity.setCellValueFactory(cellData -> cellData.getValue().cityProperty());

        // Read values from database to TableView
        Session s = getFactory().openSession();
        TypedQuery<Person> query = s.createQuery("from Person", Person.class);
        List<Person> persons = query.getResultList();
        s.close();

        tableView.getItems().addAll(persons);

        // Bind TextFields to Model
        currentPerson = new Person();
        firstName.textProperty().bindBidirectional(currentPerson.firstNameProperty());
        lastName.textProperty().bindBidirectional(currentPerson.lastNameProperty());
        street.textProperty().bindBidirectional(currentPerson.streetProperty());
        zip.textProperty().bindBidirectional(currentPerson.zipProperty(), new NumberStringConverter());
        city.textProperty().bindBidirectional(currentPerson.cityProperty());


        // This does not work because apparently, newValue is read-only
        tableView.getSelectionModel().selectedItemProperty().addListener((v, oldValue, newValue) -> {
            currentPerson = newValue;
        });
    }

    public void savePerson() {
        Session s = getFactory().openSession();
        s.getTransaction().begin();
        s.persist(currentPerson);
        s.getTransaction().commit();
        s.close();
        tableView.getItems().add(currentPerson);

        // Todo: Create new, empty Person object and map it to TextFields
        // Better solution?
    }
}

这是FXML文件:     

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>


<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" spacing="5.0" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="test.gui.MainWindowController">
   <children>
      <GridPane hgap="5.0" vgap="5.0">
        <columnConstraints>
          <ColumnConstraints hgrow="NEVER" minWidth="10.0" prefWidth="100.0" />
          <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
            <ColumnConstraints hgrow="NEVER" minWidth="10.0" prefWidth="100.0" />
            <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
        </columnConstraints>
        <rowConstraints>
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        </rowConstraints>
         <children>
            <Label text="First Name" />
            <Label text="Last Name" GridPane.rowIndex="1" />
            <Label text="Street" GridPane.rowIndex="2" />
            <Label text="ZIP" GridPane.columnIndex="2" />
            <Label text="City" GridPane.columnIndex="2" GridPane.rowIndex="1" />
            <TextField fx:id="firstName" GridPane.columnIndex="1" />
            <TextField fx:id="lastName" GridPane.columnIndex="1" GridPane.rowIndex="1" />
            <TextField fx:id="street" GridPane.columnIndex="1" GridPane.rowIndex="2" />
            <TextField fx:id="zip" GridPane.columnIndex="3" />
            <TextField fx:id="city" GridPane.columnIndex="3" GridPane.rowIndex="1" />
            <Button fx:id="saveButton" mnemonicParsing="false" onAction="#savePerson" text="Save" GridPane.columnIndex="3" GridPane.rowIndex="2" />
         </children>
      </GridPane>
      <TableView fx:id="tableView" prefHeight="200.0" prefWidth="200.0">
        <columns>
          <TableColumn fx:id="tblFirstName" prefWidth="75.0" text="First Name" />
          <TableColumn fx:id="tblLastName" prefWidth="75.0" text="Last Name" />
            <TableColumn fx:id="tblStreet" prefWidth="75.0" text="Street" />
            <TableColumn fx:id="tblZip" prefWidth="75.0" text="Zip" />
            <TableColumn fx:id="tblCity" prefWidth="75.0" text="City" />
        </columns>
      </TableView>
   </children>
   <padding>
      <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
   </padding>
</VBox>

非常感谢您。

0 个答案:

没有答案