Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在文件中可靠存储java对象的最少代码_Java_Xml_Jaxb_File Storage - Fatal编程技术网

在文件中可靠存储java对象的最少代码

在文件中可靠存储java对象的最少代码,java,xml,jaxb,file-storage,Java,Xml,Jaxb,File Storage,在我的小型独立Java应用程序中,我想存储信息 我的要求: 读写java对象(我不想使用SQL,也不需要查询) 易于使用 易于设置 最小外部依赖 因此,我希望使用jaxb将所有信息存储在文件系统中一个简单的XML文件中。我的示例应用程序如下所示(将所有代码复制到名为application.java的文件中,然后编译,无其他要求!): @XmlRootElement 类数据存储{ 字符串电子邮件地址; 列出家庭成员; //列出地址; } 公共类应用程序{ 私有静态jaxbcontextjc;

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

我的要求:

  • 读写java对象(我不想使用SQL,也不需要查询)
  • 易于使用
  • 易于设置
  • 最小外部依赖
因此,我希望使用jaxb将所有信息存储在文件系统中一个简单的XML文件中。我的示例应用程序如下所示(将所有代码复制到名为
application.java
的文件中,然后编译,无其他要求!):

@XmlRootElement
类数据存储{
字符串电子邮件地址;
列出家庭成员;
//列出地址;
}
公共类应用程序{
私有静态jaxbcontextjc;
私有静态文件storageLocation=新文件(“data.xml”);
公共静态void main(字符串[]args)引发异常{
jc=JAXBContext.newInstance(DataStorage.class);
数据存储数据存储=加载();
//主应用程序将在此处执行
//像这样的数据操作:
dataStorage.emailAddress=”me@example.com";
dataStorage.familyMembers.add(“Mike”);
保存(数据存储);
}
受保护的静态数据存储加载()引发JAXBEException{
if(storageLocation.exists()){
StreamSource source=新的StreamSource(storageLocation);
返回(数据存储)jc.createUnmarshaller().unmarshal(源);
}
返回新的数据存储();
}
受保护的静态void save(DataStorage DataStorage)引发JAXBEException{
jc.createMarshaller().marshal(数据存储、存储位置);
}
}
我如何克服这些缺点

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

了解您的需求:

  • 多次启动应用程序
  • 多个用户可以在网络驱动器上运行应用程序
  • 防止数据损坏
我认为基于XML的文件系统是不够的<如果你认为一个适当的关系数据库是多余的,你仍然可以选择一个.< /强>。这是一个超轻量级的DB,可以解决以上所有这些问题(即使不是很完美,但肯定比手写XML数据库要好得多),并且仍然很容易安装和维护。 您可以将其配置为将更改持久化到磁盘,可以将其配置为作为独立服务器运行并接受多个连接,也可以在嵌入式模式下作为应用程序的一部分运行

关于“如何保存数据”部分:

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

“您保存了什么”

H2是一个关系数据库。所以无论你保存什么,它都会以列的形式结束。但是如果您确实不打算查询数据(也不在数据上应用迁移脚本),则可以选择保存已序列化的XML对象。您可以轻松地定义一个ID+data varchar列的表,并将xml保存在该表中。H2DB中的数据长度没有限制


注意:在关系数据库中保存XML通常不是一个好主意。我只是建议您评估此选项,因为您似乎很自信,您只需要SQL实现所能提供的一组特定功能。

考虑了一会儿后,我想尝试这样实现它:

  • 打开带有最新时间戳的
    data..xml
    -文件
  • 仅使用只读模式
  • 做出改变
  • 将文件另存为
    data..xml
    -不要覆盖并检查是否不存在具有较新时间戳的文件

不一致性和并发性通过两种方式处理:

  • 通过锁定
  • 通过版本控制
在应用程序级别无法很好地处理损坏的写入。文件系统应支持日志记录,日志记录在一定程度上试图解决这一问题。你也可以这样做

  • 制作您自己的日志文件(即,包含要提交到实际数据文件的更改的短期独立文件)
所有这些特性即使在最简单的关系数据库中也可用,例如H2、SQLite,甚至网页也可以在HTML5中使用这些特性。从零开始重新实现这些功能是一件非常过分的事情,而数据存储层的正确实现实际上会使您的简单需求变得非常复杂

但是,为了记录在案:

带锁的并发处理
  • 在开始更改xml之前,请使用文件锁获得对该文件的独占访问权,另请参见
  • 更新完成并成功关闭文件后,释放锁
使用锁处理一致性(原子性)
  • 当其中一个应用程序正在写入文件时,其他应用程序实例仍可能尝试读取该文件。这可能会导致不一致(即脏读)。确保在写入过程中,写入程序进程对文件具有独占锁定。如果无法获得独占访问锁,则写入程序必须稍等片刻,然后重试

  • 读取该文件的应用程序应读取该文件(如果它可以获得访问权限,则没有其他实例执行独占锁定),然后关闭该文件。如果无法读取(由于其他应用程序锁定),请等待并重试

  • 但外部应用程序(如记事本)仍可以更改xml。在读取文件时,您可能更喜欢独占读取锁定

巴斯
@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);
    }
}