In meiner kleinen, eigenständigen Java-Anwendung möchte ich Informationen speichern.
Meine Anforderungen:
Ich möchte daher jaxb verwenden, um alle Informationen in einer einfachen XML-Datei im Dateisystem zu speichern . Meine Beispielanwendung sieht so aus (kopiere den gesamten Code in eine Datei namens Application.java
und kompiliere, keine zusätzlichen Anforderungen! !):
Wie kann ich diese Nachteile überwinden?
Um Ihre drei Probleme zu beantworten, die Sie erwähnt haben:
Warum würde es zu Inkonsistenzen führen? Wenn das, was Sie meinen, mehrere gleichzeitige Bearbeitung ist, führt zu Inkonsistenzen, Sie müssen nur die Datei vor der Bearbeitung sperren. Der einfachste Weg, eine Sperrdatei neben der Datei zu erstellen. Überprüfen Sie vor dem Bearbeiten, ob eine Sperrdatei existiert.
Wenn Sie es fehlertoleranter machen möchten, können Sie auch eine Zeitüberschreitung für die Datei festlegen. z.B. Eine Sperrdatei ist 10 Minuten lang gültig. Sie könnten eine zufällig erzeugte UUID in die Lockdatei schreiben und vor dem Speichern könnten Sie überprüfen, ob die UUID stil übereinstimmt.
Ich denke, das ist das Gleiche wie Nummer 1.
Dies kann gelöst werden, indem der Schreibatom oder die Datei unveränderlich gemacht wird. Um es atomar zu machen, kopieren Sie die Datei direkt, anstatt die Datei direkt zu bearbeiten, und bearbeiten Sie sie auf der Kopie. Nachdem die Kopie gespeichert wurde, benennen Sie einfach die Dateien um. Aber wenn Sie auf der sicheren Seite sein möchten, könnten Sie immer Dinge wie den Zeitstempel an die Datei anhängen und niemals eine Datei bearbeiten oder löschen. Jedes Mal, wenn eine Bearbeitung vorgenommen wird, erstellen Sie eine Kopie davon, wobei ein neuerer Zeitstempel an die Datei angehängt wird. Und zum Lesen lesen Sie immer das Neueste.
Ihre Anforderungen sehen:
Ich glaube, dass ein XML-basiertes Dateisystem nicht ausreichen wird. Wenn Sie eine richtige relationale Datenbank als Overkill betrachten, können Sie trotzdem eine H2 db auswählen. Dies ist eine superleichte db, die all diese oben genannten Probleme löst (wenn auch nicht perfekt, aber sicherlich viel besser als eine handgeschriebene XML-db) und dennoch sehr einfach einzurichten und zu warten ist.
Sie können es so konfigurieren, dass Ihre Änderungen auf der Festplatte beibehalten werden. Es kann so konfiguriert werden, dass es als eigenständiger Server ausgeführt wird und mehrere Verbindungen akzeptiert oder als Teil Ihrer Anwendung im Embedded-Modus ausgeführt werden kann.
Zum "Wie speichern Sie die Daten" :
Wenn Sie keine erweiterte ORM-Bibliothek (wie Hibernate oder eine andere JPA-Implementierung) verwenden möchten, können Sie immer noch einfach alte JDBC verwenden. Oder zumindest einige Spring-JDBC, die sehr leicht und einfach zu bedienen ist.
"Was speichern Sie?"
H2 ist eine relationale Datenbank. Also was auch immer du speicherst, es wird in Spalten enden. Aber! Wenn Sie wirklich nicht beabsichtigen, Ihre Daten abzufragen (und keine Migrationsskripte darauf anwenden), können Sie Ihre bereits XML-serialisierten Objekte speichern ist eine Option. Sie können einfach eine Tabelle mit einer ID + einer varchar-Spalte "data" definieren und dort Ihre XML-Datei speichern. Es gibt keine Begrenzung der Datenlänge in H2DB.
Hinweis: Das Speichern von XML in einer relationalen Datenbank ist im Allgemeinen keine gute Idee. Ich rate Ihnen nur, diese Option zu bewerten, weil Sie sicher sind, dass Sie nur eine bestimmte Menge von Funktionen benötigen, die eine SQL-Implementierung bereitstellen kann.
Inkonsistenzen und Parallelität werden auf zwei Arten behandelt:
Beschädigtes Schreiben kann auf Anwendungsebene nicht gut behandelt werden. Das Dateisystem soll das Journaling unterstützen, das versucht, das bis zu einem gewissen Grad zu beheben. Sie können dies auch durch
tunAlle diese Merkmale sind sogar in der einfachsten relationalen Datenbank verfügbar, z. H2, SQLite und sogar eine Webseite können solche Funktionen in HTML5 verwenden. Es ist ein ziemlicher Overkill, diese von Grund auf neu zu implementieren, und die richtige Implementierung der Datenspeicherschicht wird Ihre einfachen Anforderungen ziemlich kompliziert machen.
Aber nur für die Aufzeichnungen:
Andere Anwendungsinstanzen versuchen möglicherweise immer noch, die Datei zu lesen, während eine der Anwendungen sie schreibt. Dies kann Inkonsistenzen verursachen (aka dirty-read). Stellen Sie sicher, dass der Writer-Prozess beim Schreiben eine exklusive Sperre für die Datei hat. Wenn es nicht möglich ist, eine exklusive Zugriffssperre zu erhalten, muss der Schreiber etwas warten und es erneut versuchen.
Eine Anwendung, die die Datei liest, muss sie lesen (wenn sie Zugriff erhält, keine anderen Instanzen eine exklusive Sperre), dann schließen Sie die Datei. Wenn das Lesen nicht möglich ist (wegen anderer App-Sperren), warten Sie und versuchen Sie es erneut.
noch eine externe Anwendung (z. B. Notepad) kann die XML ändern. Sie können beim Lesen der Datei eine exklusive Lesesperre bevorzugen.
Hier ist die Idee, wenn Sie viel schreiben müssen (oder wenn Sie später vielleicht Ihre Schreibvorgänge rückgängig machen wollen), wollen Sie die reale Datei nicht berühren. Stattdessen:
schreibt Änderungen an eine separate Journaldatei, die von Ihrer App-Instanz erstellt und gesperrt wird
Ihre App-Instanz sperrt die Hauptdatei nicht, sie sperrt nur die Journaldatei
, wenn alle Schreibvorgänge sind gut zu gehen, die App öffnet die eigentliche Datei mit exklusiver Schreibsperre, und verpflichtet jede Änderung in der Journaling-Datei, dann schließen Sie die Datei.
Wie Sie sehen, macht die Lösung mit Sperren die Datei zu einer freigegebenen Ressource, die durch Sperren geschützt ist und nur eine Anwendung gleichzeitig auf die Datei zugreifen kann. Dies behebt die Nebenläufigkeitsprobleme, macht aber auch den Dateizugriff zu einem Engpass. Daher verwenden moderne Datenbanken wie Oracle die Versionierung statt Sperren. Die Versionierung bedeutet, dass sowohl die alte als auch die neue Version der Datei zur gleichen Zeit verfügbar sind. Leser werden mit der alten, vollständigsten Datei bedient. Sobald das Schreiben der neuen Version abgeschlossen ist, wird es mit der alten Version zusammengeführt und die neuen Daten werden sofort verfügbar. Dies ist schwieriger zu implementieren, aber da es ermöglicht, die Zeit für alle Anwendungen parallel zu lesen, skaliert es viel besser.
Beachten Sie, dass Ihre einfache Antwort nicht gleichzeitige Schreibvorgänge von verschiedenen Instanzen behandelt. Wenn zwei Instanzen Änderungen vornehmen und speichern, werden durch das Auswählen des neuesten die Änderungen der anderen Instanz verloren gehen. Wie in anderen Antworten erwähnt, sollten Sie wahrscheinlich versuchen, Dateisperrung dafür zu verwenden.
eine relativ einfache Lösung:
Nachdem ich eine Weile darüber nachgedacht habe, möchte ich versuchen, es so umzusetzen:
data.<timestamp>.xml
-Datei mit dem neuesten Zeitstempel. data.<timestamp>.xml
- überschreiben Sie nicht und prüfen Sie, ob keine Datei mit neuerem Zeitstempel existiert. Tags und Links java xml jaxb file-storage