将java对象可靠地存储在文件中的最小代码

sla*_*dan 8 java xml jaxb file-storage

在我的小型独立Java应用程序中,我想存储信息.

我的要求:

  • 读取和写入java对象(我不想使用SQL,也不需要查询)
  • 使用方便
  • 易于设置
  • 最小的外部依赖

因此,我想使用jaxb将所有信息存储在文件系统中的简单XML文件中.我的示例应用程序看起来像这样(将所有代码复制到一个名为Application.java和编译的文件中,没有其他要求!):

@XmlRootElement
class DataStorage {
    String emailAddress;
    List<String> familyMembers;
    // List<Address> addresses;
}

public class Application {

    private static JAXBContext jc;
    private static File storageLocation = new File("data.xml");

    public static void main(String[] args) throws Exception {
        jc = JAXBContext.newInstance(DataStorage.class);

        DataStorage dataStorage = load();

        // the main application will be executed here

        // data manipulation like this:
        dataStorage.emailAddress = "me@example.com";
        dataStorage.familyMembers.add("Mike");

        save(dataStorage);
    }

    protected static DataStorage load() throws JAXBException {
        if (storageLocation.exists()) {
            StreamSource source = new StreamSource(storageLocation);
            return (DataStorage) jc.createUnmarshaller().unmarshal(source);
        }
        return new DataStorage();
    }

    protected static void save(DataStorage dataStorage) throws JAXBException {
        jc.createMarshaller().marshal(dataStorage, storageLocation);
    }
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能克服这些缺点?

  • 多次启动应用程序可能会导致不一致:多个用户可以在网络驱动器上运行该应用程序并遇到并发问题
  • 中止写入过程可能会导致数据损坏或丢失所有数据

Ger*_*cso 7

看到你的要求:

  • 多次启动应用程序
  • 有几个用户可以在网络驱动器上运行该应用程序
  • 防止数据损坏

我相信基于XML的文件系统是不够的.如果你认为一个适当的关系数据库是一个过度杀伤,你仍然可以去一个H2数据库.这是一个超轻量级的数据库,它可以解决上面的所有这些问题(即使不是很完美,但肯定比手写的XML数据库好得多),并且仍然很容易设置和维护.

您可以将其配置为将更改保留到磁盘,可以配置为作为独立服务器运行并接受多个连接,也可以在嵌入模式下作为应用程序的一部分运行.

关于"如何保存数据"部分:

如果您不想使用任何高级ORM库(如Hibernate或任何其他JPA实现),您仍然可以使用普通的旧JDBC.或者至少有一些Spring-JDBC,它非常轻巧且易于使用.

"你拯救了什么"

H2是关系数据库.所以无论你保存什么,它都会以列的形式出现.但!如果您确实不打算查询数据(既不在其上应用迁移脚本),则可以选择保存已经XML序列化的对象.您可以轻松定义具有ID +"data"varchar列的表,并将xml保存在那里.H2DB中的数据长度没有限制.

注意:在关系数据库中保存XML通常不是一个好主意.我只建议您评估此选项,因为您似乎确信您只需要SQL实现可以提供的某些功能集.


Row*_*nto 2

回答你提到的三个问题:

多次启动应用程序可能会导致不一致

为什么会导致不一致呢?如果您的意思是多个并发编辑会导致不一致,您只需在编辑之前锁定文件即可。最简单的方法是在文件旁边创建一个锁定文件。在开始编辑之前,只需检查锁定文件是否存在。

如果您想让它更具容错性,您还可以对文件设置超时。例如,锁定文件的有效期为 10 分钟。您可以在锁定文件中写入随机生成的 uuid,在保存之前,您可以检查 uuid 是否仍然匹配。

多个用户可以在网络驱动器上运行应用程序并遇到并发问题

我认为这与第一点相同。

中止写入过程可能会导致数据损坏或丢失所有数据

这可以通过使写入原子化或文件不可变来解决。要使其原子化,只需复制文件,然后在副本上进行编辑,而不是直接编辑文件。保存副本后,只需重命名文件即可。但如果您想更安全,您始终可以执行诸如在文件上附加时间戳之类的操作,并且永远不要编辑或删除文件。因此,每次进行编辑时,您都会创建它的副本,并在文件上附加更新的时间戳。对于阅读,您将始终阅读最新的内容。