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