【问题标题】:How to implement save/load functionality of Java application data/state?如何实现 Java 应用程序数据/状态的保存/加载功能?
【发布时间】:2019-04-12 04:05:15
【问题描述】:

我有一个 POJO(普通的旧 Java 对象)应用程序来表示我的数据。

在运行时,应用程序会根据需要操作和记住数据。

现在我想实现一个保存/加载功能。


我不是在询问基本文件 I/O。

我不是在问 ObjectOutputStream 是否存在。


我发现的选项如下:

1) Gson、Jackson 等 JSON/XML/YAML 库

2) 滚动您自己的二进制文件格式,使用序列化代理模式将所有内容标记为可序列化。

选项 1 不合适,因为我的数据模型可以具有循环引用。 Gson 导致堆栈溢出。

选项2不合适,因为文件应该是跨平台的并且独立于JVM;它应该适用于桌面和android java。

由于模型的复杂性,属性文件显然也不合适。


请不要攻击我的用例;我的数据模型设计得非常好。这个例子可能不是。

我现在将给出需要保存的那种结构的示例代码。

class Application {

    //This College is my top level object. It could correspond to an individual save file.
    College college = new College();

    //I would love to be able to just throw this guy into a file.
    SomeLibrary.writeToFile(college);
    //And read another back.
    College college2 = SomeLibrary.readFromFile(anotherCollege);
}

class College {
    //The trees are implemented recursively, so this is actually just the root of each tree.
    Tree<Course> artCourseTree;
    Tree<Course> engineeringCourseTree;
    Tree<Course> businessCourseTree;

    List<Student> maleStudents;
    List<Student> femaleStudents;
}

class Course {
    //Each course only has 2 students in this example. Ignore.
    Student student1;
    Student student2;

    List<Exam> examsInCourse;
    LocalDate courseStartDate;
    Period duration;
}

class Student {
    String name;
    List<Exam> listOfExamsTaken;
}

class Exam {
    Student studentTakingIt;
    LocalDate dateTaken;
    BigDecimal score;
}

如您所见,Exams 旨在成为此模型中位于层次结构底部的原子对象。但是,它们不仅被 Student 和 Courses 引用,而且还引用回 Student 并包含非原始数据,例如 LocalDate 和 BigDecimal。该模型通过引用不同课程和学生的不同考试子集来赋予意义。

我需要保存关系、这些东西的排列、这些东西的任意数量,以及它们持有的数据。

我对保存和加载这样的模型有什么希望?

有哪些选项可以在具有此类约束的此类模型上实现保存/加载功能?


每个java程序都滚动自己的二进制文件格式并创建一个可怕的设备来序列化和反序列化所有东西真的是行业标准吗?是那个还是JSON?我在这里想念什么?我是否必须以某种方式对虚拟机进行快照?为什么没有这方面的标准做法?

【问题讨论】:

  • “硬”方式,可能是用生成的“密钥”存储“数据”(只要它对文件有效就没有关系),然后使用这些密钥存储关系一个单独的部分......你看过JAXP吗?
  • 我没有详细了解 JAXP,因为我理解它是一个 XML 实用程序,我认为它在循环引用方面会受到与 JSON 相同的限制。有错吗?
  • 我不能确定你的实现,但它是基于注释的,所以你可以更好地控制解析的完成方式
  • 我也在制定一些解决方案,在其中减少对某些唯一对象标识符的引用(例如 toString() 或其他东西)并分别存储对象及其关系。我会坚持一个更简单的解决方案。
  • 与 ms office “搞混”,他们倾向于做类似的事情????

标签: java


【解决方案1】:

循环引用是一个常见的用例,可以通过提供@JsonManagedReference@JsonBackReference 来处理。查看this SO answer了解更多详情。另一种选择是实现自定义序列化程序并自行解决循环引用。 Here 是同样的例子。

但是,在继续使用文件作为数据库之前,请考虑以下方面

  • 您必须自己管理并发写入。如果处理不当,可能会导致数据损坏/丢失,因为文件本质上不符合 ACID
  • 随着文件大小的增长,该解决方案不可扩展。序列化和反序列化的时间将成比例增加。
  • 您将无法轻松查询文件中存储的数据。您总是必须先反序列化数据,然后再查询 POJO。

我强烈建议检查 SQLite,它是小型、快速、独立、高可靠性、全功能的 SQL 数据库引擎。

【讨论】:

  • 我现在看到 Jackson 没有 gson 的限制,可以处理循环引用。您还包括另一个涉及自定义序列化程序的选项。出于这些原因,我会在一些测试后将此标记为答案。
  • 对使用文件作为数据库的注意事项表示赞赏,但我不知道这个意图是从哪里发出的。
  • 所以我得出这样的结论是否正确,一般来说,每个人要么使用自定义序列化,要么使用 json/xml 库?
  • 是的,上面的循环引用是解决方案。关于将文件作为 db 的注释,状态是数据并将其转储到文件中并从文件中读取是一种做数据库的事情,不是吗? :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-02
  • 1970-01-01
  • 2012-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-11
相关资源
最近更新 更多