写入/读取嵌套的ObservableList';来自JavaFX应用程序的

写入/读取嵌套的ObservableList';来自JavaFX应用程序的,java,serialization,javafx,jaxb,observablelist,Java,Serialization,Javafx,Jaxb,Observablelist,我正在编写一个小型JavaFx应用程序,其中主类包含一个用户的ObservableArryList。这些用户有账户的可观察列表,这些账户有交易的可观察列表等等 下面是类图: 我想将应用程序的数据保存并在以后读取到/fram文件中 我已经尝试通过在所有类中实现Serializable接口来保存它,但显然您无法序列化ObservableList 我还尝试使用Gson将其保存在Json文件中,或者使用JAXB将其保存为XML文件,但它们都没有递归地存储列表 所以我的问题是: 有人知道我如何保存当前应用

我正在编写一个小型JavaFx应用程序,其中主类包含一个用户的ObservableArryList。这些用户有账户的可观察列表,这些账户有交易的可观察列表等等

下面是类图:

我想将应用程序的数据保存并在以后读取到/fram文件中

我已经尝试通过在所有类中实现Serializable接口来保存它,但显然您无法序列化ObservableList

我还尝试使用Gson将其保存在Json文件中,或者使用JAXB将其保存为XML文件,但它们都没有递归地存储列表

所以我的问题是: 有人知道我如何保存当前应用程序中的所有对象,然后稍后再次加载它们吗

编辑:
我实现了jewelsea提供的基于JAXB的存储方法,数据的保存/加载现在运行良好。

通用设计方法建议

对于您的问题,我倾向于使用数据库而不是序列化。根据你的需要,有很多选择。对于一个小型嵌入式数据库,类似的东西将是一个合理的选择。这里提供了一个集成示例

对于持久性,您可以使用纯JDBC或JPA。对于大量应用,JPA将更好。对于小型应用程序,JDBC就足够了。如果您使用JPA,您可以将其与JavaFX基于属性的类集成,如链接到和本文的文章中所定义。但是,您可能希望将JavaFX视图模型属性对象分开,并使用一个用于持久化的。将对象分开可以在应用程序设计和实现中提供更多的灵活性,但这违反了原则。不过这是一个折衷方案,因为生成的对象更好地尊重环境

为每个实体(用户、帐户、收件人、事务)定义单独的表。为每个实体条目分配一个唯一的id键。用于链接存储在ObservableList中的项目引用

如果您希望从远程位置访问数据库,但无法打开与数据库的直接端口连接,则需要在提供数据的服务器上提供服务(例如,一个基于REST的服务器,它执行数据库访问,并通过HTTP将所需数据公开为JSON,您的JavaFX客户端通过REST客户端访问该数据,然后将REST调用响应处理为基于客户端JavaFX属性的数据结构)。这样的实现很快就会成为大量工作:-)

也许我不应该回答这个问题,因为根据StackOverflow原则,这个问题(或我对它的解释)太宽泛了,但希望这里的信息对您有用

基于其他信息的具体答案

实际上,我已经有了一个基于SpringBoot的web应用程序,它使用DAO和Hibernate运行良好,这个JavaFX应用程序计划连接到该web应用程序。我只需要这个本地保存的文件作为一个小“演示”的程序,如果目前没有互联网连接可用

明白了,这完全有道理。我以前已经将JavaFX与SpringBoot集成,但不幸的是,我无法公开发布这些实现的源代码

对于您的演示程序,通过JAXB或Jackson进行持久化就足够了。为基于JAXB的JavaFX持久化提供了一个很好的示例

基于JAXB的方法的诀窍是获得与嵌套数据模型一起工作的东西

基于JAXB的存储方法示例

这个例子是基于来自美国的想法。要更好地理解它,请参阅教程。嵌套的可观察列表持久性是使用以下概念实现的:

解决方案的关键是
User
类中的这一位代码。它将帐户列表作为嵌套的ObservableList提供,并根据JavaFX约定提供标准访问器
accounts()
来检索
ObservableList
。它还提供了一个
getAccounts()
setAccounts()
方法,该方法将ObservableList的进出复制到一个标准Java列表,并使用JAXB
@Xml…
注释来标记getter,以使JAXB能够处理链接到用户的帐户的序列化和反序列化

private final ObservableList<Account> accounts = FXCollections.observableArrayList();

public ObservableList<Account> accounts() { return accounts; }

@XmlElementWrapper(name="accounts")
@XmlElement(name = "account")
public List<Account> getAccounts() {
    return new ArrayList<>(accounts);
}

public void setAccounts(List<Account> accounts) {
    this.accounts.setAll(accounts);
}
输出

$cat/Users/jewelsea/user account.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<users>
    <user>
        <accounts>
            <account>
                <balance>10</balance>
                <id>a17b8244-5d3a-4fb4-a992-da26f4e14917</id>
            </account>
            <account>
                <balance>20</balance>
                <id>f0b23df5-3cc0-418c-9840-633bc0f0b3ca</id>
            </account>
        </accounts>
        <firstName>Hans</firstName>
        <id>078dad74-ea9d-407d-9be5-d36c52c53b0d</id>
        <lastName>Muster</lastName>
    </user>
    <user>
        <accounts/>
        <firstName>Ruth</firstName>
        <id>78513f1b-75ee-4ca9-a6f0-444f517e3377</id>
        <lastName>Mueller</lastName>
    </user>
    <user>
        <accounts>
            <account>
                <balance>15</balance>
                <id>77c4fd3c-5f7a-46cf-a806-da1e6f93baab</id>
            </account>
        </accounts>
        <firstName>Heinz</firstName>
        <id>651d9206-42a5-4b76-b89e-be46dce8df74</id>
        <lastName>Kurz</lastName>
    </user>
</users>

10
a17b8244-5d3a-4fb4-a992-da26f4e14917
20
f0b23df5-3cc0-418c-9840-633bc0f0b3ca
汉斯
078dad74-ea9d-407d-9be5-d36c52c53b0d
集合
露丝
78513f1b-75ee-4ca9-a6f0-444f517e3377
米勒
15
77c4fd3c-5f7a-46cf-a806-da1e6f93baab
亨氏
651d9206-42a5-4b76-b89e-be46dce8df74
库兹

非常感谢您的快速回答!实际上,我已经有了一个基于SpringBoot的web应用程序,它使用DAO和Hibernate运行良好,这个JavaFX应用程序计划连接到该web应用程序。我只需要这个本地保存的文件作为一个小“演示”的程序,如果目前没有互联网连接可用。我一定会查看您提供的H2示例!我用您提供的新JAXB示例更新了这个问题@UniqUnicorn我不知道为什么解组对您的代码版本不起作用。我在回答中仔细检查了代码,解组正在为我提供的代码工作。我不知道您在实现过程中体验到的行为差异的原因。非常酷。将此小模式与JSON(Jackson)一起使用,并立即生效。
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "users")
public class UserListWrapper {

    private List<User> persons;

    @XmlElement(name = "user")
    public List<User> getPersons() {
        return persons;
    }

    public void setPersons(List<User> persons) {
        this.persons = persons;
    }
}
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class User {
    private final StringProperty id;
    private final StringProperty firstName;
    private final StringProperty lastName;

    private final ObservableList<Account> accounts = FXCollections.observableArrayList();

    public User() {
        this(UUID.randomUUID().toString(), null, null);
    }

    public User(String firstName, String lastName) {
        this(UUID.randomUUID().toString(), firstName, lastName);
    }

    public User(String id, String firstName, String lastName) {
        this.id = new SimpleStringProperty(id);
        this.firstName = new SimpleStringProperty(firstName);
        this.lastName = new SimpleStringProperty(lastName);
    }

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

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

    public StringProperty idProperty() {
        return id;
    }

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

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

    public StringProperty firstNameProperty() {
        return firstName;
    }

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

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

    public StringProperty lastNameProperty() {
        return lastName;
    }

    public ObservableList<Account> accounts() { return accounts; }

    @XmlElementWrapper(name="accounts")
    @XmlElement(name = "account")
    public List<Account> getAccounts() {
        return new ArrayList<>(accounts);
    }

    public void setAccounts(List<Account> accounts) {
        this.accounts.setAll(accounts);
    }

}
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

import java.util.UUID;

public class Account {
    private final StringProperty id;
    private final IntegerProperty balance;

    public Account() {
        this(UUID.randomUUID().toString(), 0);
    }

    public Account(int balance) {
        this(UUID.randomUUID().toString(), balance);
    }

    public Account(String id, int balance) {
        this.id = new SimpleStringProperty(id);
        this.balance = new SimpleIntegerProperty(balance);
    }

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

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

    public StringProperty idProperty() {
        return id;
    }

    public int getBalance() {
        return balance.get();
    }

    public IntegerProperty balanceProperty() {
        return balance;
    }

    public void setBalance(int balance) {
        this.balance.set(balance);
    }
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<users>
    <user>
        <accounts>
            <account>
                <balance>10</balance>
                <id>a17b8244-5d3a-4fb4-a992-da26f4e14917</id>
            </account>
            <account>
                <balance>20</balance>
                <id>f0b23df5-3cc0-418c-9840-633bc0f0b3ca</id>
            </account>
        </accounts>
        <firstName>Hans</firstName>
        <id>078dad74-ea9d-407d-9be5-d36c52c53b0d</id>
        <lastName>Muster</lastName>
    </user>
    <user>
        <accounts/>
        <firstName>Ruth</firstName>
        <id>78513f1b-75ee-4ca9-a6f0-444f517e3377</id>
        <lastName>Mueller</lastName>
    </user>
    <user>
        <accounts>
            <account>
                <balance>15</balance>
                <id>77c4fd3c-5f7a-46cf-a806-da1e6f93baab</id>
            </account>
        </accounts>
        <firstName>Heinz</firstName>
        <id>651d9206-42a5-4b76-b89e-be46dce8df74</id>
        <lastName>Kurz</lastName>
    </user>
</users>