JavaFX MVC应用程序与数据库的最佳实践

 2023-02-16    319  

问题描述

我是Javafx的新手,我想知道开发MVC数据库应用程序的最佳实践是什么,我认为如果您是高级开发人员,我的问题将非常简单.

让我们考虑一个简单的示例Javafx中开发的基本应用程序:与SQL数据库链接的Todolist.

JavaFX MVC应用程序与数据库的最佳实践

  • 数据库只是一个表任务,带有 id 和a taskdescr varchar字段.
  • 目的非常容易:我们只想在表观视图或ListView中显示任务,并能够添加一些任务.

这就是我们的应用程序的样子:

todolist gui

我决定将代码分为四个部分, dao 对于代表表(task.java)的类的类,访问数据库的dao类(其行为在这里无关紧要). 模型代表我们的托尔氏师的模型一部分(包含任务列表并在其上执行操作,调用DAO等). FXML 视图和控制器:

项目结构

接下来,您可以找到我们感兴趣的不同类的代码(我们认为DAO还可以(自动设置ID)我们不处理错误案例以简化代码:

task.java

public class Task {

    private int id;
    private SimpleStringProperty task;

    public Task(int i, String s){
        this.id = i;
        this.task = new SimpleStringProperty(s);
    }

    public void setId(int i){
        this.id = i;
    }

    public int getId() {
        return id;
    }

    public String getTask() {
        return task.get();
    }

    public void setTask(String task) {
        this.task.set(task);
    }

    @Override
    public boolean equals(Object o){
        if(this.id == ((Task)o).id)
            return true;
        return false;
    }
}

todolistmodel.java

public class ToDoListModel {

    private List<Task> taskList;
    private DAO dao;

    public ToDoListModel(){
        this.taskList = new ArrayList<Task>();
        this.dao = new DAO();
    }

    public void loadDatabase(){
        this.taskList = this.dao.getAllTasks();
    }

    public void addTask(Task t){
        // Operations throwing Exceptions such as : Does the task t is already in the list, etc...
        this.taskList.add(t);
        this.dao.createTask(t);
    }

    public void deleteTask(Task t){
        this.taskList.remove(t);
        this.dao.deleteTask(t);
    }

    public List<Task> getTaskList() {
        return taskList;
    }
}

controller.java

public class Controller {

    private final ToDoListModel model;

    @FXML
    private TableView<Task> taskTable;
    @FXML
    private TableColumn<Task, String> taskColumn;
    @FXML
    private TextField taskTextField;

    public Controller(ToDoListModel m){
        this.model = m;
    }

    @FXML
    protected void initialize() {
        this.model.loadDatabase();

        // Setting up data table
        taskColumn.setCellValueFactory(new PropertyValueFactory<Task, String>("task"));
        ObservableList<Task> taskObservableList = FXCollections.observableList(this.model.getTaskList());
        taskTable.setItems(taskObservableList);
    }

    @FXML
    public void handleAddButton(ActionEvent e) {
        Task t = new Task(-1, this.taskTextField.getText());

        // What operations to do here ?
        this.model.addTask(t);
        this.taskTable.getItems().add(t);
        this.taskTable.refresh();
    }

}

main.java

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        ToDoListModel model = new ToDoListModel();
        primaryStage.setTitle("My Todo");
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(getClass().getResource("views/View.fxml"));
        loader.setController(new Controller(model));
        Parent root = loader.load();
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

最后,我的问题是:我的方法好吗?我的意思是,我已经创建了一个带有任务列表的todolistModel,这一事实是我在与DAO的同一任务上更新对象 task task DAO将在列表中的添加之后执行),最重要的是:我的控制器的 handleaddbutton 我应该执行什么操作?在这里,我首先在todolistModel中使用了添加方法,但这还不够,因为我可观察到的列表已错误地更新(出现了添加的任务,但我们无法使用鼠标选择它).然后,当我在桌面项目中也添加它时,任务出现两次,并在列表中添加了两次.

因此,我了解到观察者链接到我的TodolistModel中的列表,但是如果我只想在模型中进行该列表上的操作,但是正确更新了ObservableStist,该怎么办? (可选项目等…)

重复示例示例

预先感谢您的帮助和耐心,
真挚地,
保罗

推荐答案

这是一个示例实现
DAO类负责连接到数据库(可能使用池或其他东西).在这种情况下,它建立了一个简单的连接.

public class DAO {
    public Connection getConnection() throws SQLException {
        return  DriverManager.getConnection("jdbc:mysql://192.168.40.5:3306/test", "root", "");
    }
}

ToDoListModel类通过使用DAO实例获得有效连接来处理数据库.

public class ToDoListModel {
    private DAO dao;

    public static ToDoListModel getInstance() {
        ToDoListModel model = new ToDoListModel();
        model.dao = new DAO();

        return model;
    }

    private ToDoListModel() {
    }

    public void addTask(Task task) throws SQLException {
        try(Connection connection = dao.getConnection()) {
            String q = "insert into todo (name) values (?)";

            try(PreparedStatement statement = connection.prepareStatement(q, Statement.RETURN_GENERATED_KEYS)) {
                statement.setString(1, task.getName());
                statement.executeUpdate();

                try(ResultSet rs = statement.getGeneratedKeys()) {
                    if(rs.next()) {
                        task.setId(rs.getInt(1));
                    }
                }
            }
        }
    }

    public void deleteTask(Task task) throws SQLException {
        try(Connection connection = dao.getConnection()) {
            String q = "delete from todo where id = ?";

            try(PreparedStatement statement = connection.prepareStatement(q)) {
                statement.setInt(1, task.getId());
                statement.executeUpdate();
            }
        }
    }

    public ObservableList<Task> getTaskList() throws SQLException {
        try(Connection connection = dao.getConnection()) {
            String q = "select * from todo";

            try(Statement statement = connection.createStatement()) {
                try(ResultSet rs = statement.executeQuery(q)) {
                    ObservableList<Task> tasks = FXCollections.observableArrayList();

                    while (rs.next()) {
                        Task task = new Task();
                        task.setId(rs.getInt("id"));
                        task.setName(rs.getString("name"));

                        tasks.add(task);
                    }

                    return tasks;
                }
            }
        }
    }
}

控制器使用ToDoListModel来初始化TableView控件并添加操作(编辑和读取 – 我没有实现它们,因为我坚持您的代码)

public class Controller {

    @FXML
    private TextField textField;

    @FXML
    private TableView<Task> tableView;

    @FXML
    private TableColumn<Task, String> nameTableColumn;

    @FXML
    private Button addButton;

    @FXML
    private void initialize() {
        nameTableColumn.setCellValueFactory(cdf -> cdf.getValue().nameProperty());

        addButton.disableProperty().bind(Bindings.isEmpty(textField.textProperty()));

        CompletableFuture.supplyAsync(this::loadAll)
            .thenAccept(list -> Platform.runLater(() -> tableView.getItems().setAll(list)))
            .exceptionally(this::errorHandle);
    }

    @FXML
    private void handleAddButton(ActionEvent event) {
        CompletableFuture.supplyAsync(this::addTask)
                .thenAccept(task -> Platform.runLater(() -> {
                    tableView.getItems().add(task);

                    textField.clear();
                    textField.requestFocus();
                }))
                .exceptionally(this::errorHandle);
    }

    private Task addTask() {
        try {
            Task task = new Task(textField.getText());
            ToDoListModel.getInstance().addTask(task);

            return task;
        }
        catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    private ObservableList<Task> loadAll() {
        try {
            return ToDoListModel.getInstance().getTaskList();
        }
        catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    private Void errorHandle(Throwable throwable) {
        throwable.printStackTrace();
        return null;
    }
}

任何数据库操作都具有CompletableFuture的异步性,但是您可以使用任何您喜欢的东西.重要的是要记住,UI线程只能由此独特.

以上所述是小编给大家介绍的JavaFX MVC应用程序与数据库的最佳实践,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/33899.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。