Umgang mit der Datenpflege in Objektdatenbanken wie db4o

8

Eine Sache, die ich bei der Verwendung einer Objektdatenbank wie db4o immer wieder als sehr verwirrend empfunden habe, ist die Art und Weise, wie man mit komplexen Aufgaben umgehen soll Migrationen, die normalerweise von SQL / PL-SQL gehandhabt werden.

Stellen Sie sich zum Beispiel vor, Sie hätten eine Tabelle in einer relationalen Datenbank namens my_users. Ursprünglich hatten Sie eine Spalte mit dem Namen "full_name", jetzt, da Ihre Software in V2 ist, möchten Sie diese Spalte entfernen, die vollständigen Namen auf ein Leerzeichen aufteilen und den ersten Teil in eine Spalte namens "first_name" und die zweite in eine Spalte schreiben Nachname_name. In SQL würde ich einfach die Spalten "first_name" und "second_name" auffüllen und dann die ursprüngliche Spalte namens "full_name" entfernen.

Wie würde ich das in etwas wie db4o machen? Schreibe ich ein Java-Programm, das nach allen Objekten von User.class sucht, wobei full_name auf null gesetzt wird, während first_name und last_name gesetzt werden? Wenn ich meinen nächsten SVN-Commit mache, wird es keine Feld / Bean-Eigenschaft geben, die full_name entspricht, wäre das ein Problem? Es sieht so aus, als würde ich es in einer Produktionsanwendung verwenden, in der sich mein "Schema" ändert. Ich möchte ein Skript schreiben, um Daten von Version x auf Version x + 1 zu migrieren und dann in Version x + 2 die Eigenschaften, die ich versuche, zu entfernen loswerden für Version x + 1, da ich kein Java-Skript schreiben kann, um Eigenschaften zu ändern, die nicht mehr Teil meines Typs sind.

Es scheint, dass ein Teil des Problems darin besteht, dass ein RDBMS auf Basis eines einfachen, auf Groß- / Kleinschreibung basierenden String-basierten Namens das Objekt, auf das Sie verweisen, auflöst. In einer Sprache wie Java ist die Eingabe komplizierter, Sie können nicht auf eine Eigenschaft verweisen Wenn das Getter / Setter / Feld kein Mitglied der zur Laufzeit geladenen Klasse ist, so dass Sie im selben Skript im Wesentlichen zwei Versionen Ihres Codes haben müssen (hmm, benutzerdefinierte Klassenladeprogramme klingen wie ein Schmerz), haben Sie die neue Version Ihrer Klasse gespeichert gehören zu einem anderen Paket (klingt chaotisch), oder verwenden Sie die Version x + 1 x + 2 Strategie, die ich erwähnte (erfordert viel mehr Planung). Vielleicht gibt es eine offensichtliche Lösung, die ich nie aus den db4o-Dokumenten herausgelesen habe.

Irgendwelche Ideen? Hoffentlich macht das einen Sinn.

    
benstpierre 10.03.2010, 20:15
quelle

2 Antworten

10

Erstens behandelt db4o das "einfache" Szenarien wie automatisches Hinzufügen oder Entfernen eines Feldes . Wenn Sie das Feld hinzufügen, wird für alle vorhandenen Objekte der Standardwert gespeichert. Wenn Sie ein Feld entfernen, befinden sich die Daten des vorhandenen Objekts immer noch in der Datenbank und Sie können weiterhin darauf zugreifen. Umbenennungsfeld usw. sind spezielle Refactoring-Aufrufe .

Jetzt würden Sie in Ihrem Szenario so etwas tun:

  1. Entfernen Sie das Feld 'full_name', fügen Sie die neuen Felder 'first_name' und 'second_name'
  2. hinzu
  3. Iteriere über alle 'Adress'-Objekte
  4. Zugriff auf das alte Feld über die 'StoredClass'-API
  5. Teilen, ändern, aktualisieren usw. den Wert. Setzen Sie die neuen Werte auf das neue Feld und speichern Sie das Objekt.

Nehmen wir an, wir haben eine 'Address'-Klasse. Das Feld 'full_name' wurde entfernt. Jetzt wollen wir es in den 'Vornamen' und 'Nachnamen' kopieren. Dann könnte es so gehen (Java):

%Vor%

Wie Sie vorgeschlagen haben, würden Sie für jeden Versionsbump einen Migrationscode schreiben. Da ein Feld nicht mehr zu Ihrer Klasse gehört, müssen Sie mit der 'StoredField'-API wie oben darauf zugreifen.

Sie können eine Liste aller 'gespeicherten' Klassen mit ObjectContainer.ext().storedClasses() erhalten. Mit StoredClass.getStoredFields() können Sie eine Liste aller Geschäftsfelder erhalten, ohne dass das Feld in Ihrer Klasse nicht mehr existiert. Wenn eine Klasse nicht mehr existiert, können Sie die Objekte noch abrufen und über die 'GenericObject'-Klasse darauf zugreifen.

Update: Für komplexere Szenarien, in denen eine Datenbank über mehrere Versionsschritte migriert werden muss.

Zum Beispiel sieht das Adressobjekt in der Version v3 völlig anders aus. Das 'migration-script' für v1 zu v2 hat also nicht mehr die benötigten Felder (Vorname und Name in meinem Beispiel). Ich denke, es gibt mehrere Möglichkeiten, damit umzugehen.

  1. (Für diese Idee wird Java vorausgesetzt. Natürlich gibt es eine Entsprechung in .NET). Sie könnten den Migrationsschritt zu einem Groovy-Skript machen. So stört jedes Skript nicht das andere. Dann definieren Sie 'Klassen' die benötigten Klassen für die Migration dort. Jede Migration hat also eigene Migrationsklassen. Mit Aliases würdest du deine groovy- migration-classes zu den eigentlichen Java-Klassen.
  2. Erstellen von Refactoring-Klassen für komplexe Szenarien. Binden Sie diese Klassen auch mit Aliasen .
Gamlor 10.03.2010, 21:25
quelle
2

Ich mache hier ein bisschen wild, weil ich in meinem Leben nicht zu viele Daten umgestaltet habe.

Sie machen einen seltsamen Vergleich: Wenn Sie die db "heiß migrieren" wollten, müssten Sie wahrscheinlich den von Ihnen beschriebenen Ansatz x+1 , x+2 versioning durchführen, aber ich weiß es nicht wirklich - Ich würde das auch nicht mit SQL machen, da ich kein db-Experte bin.

Wenn Sie jedoch "kalt" migrieren, können Sie dies in einem Schritt tun, indem Sie ein neues Objekt aus den alten Daten instanziieren, das neue Objekt speichern und das alte Objekt für jedes Objekt im Geschäft löschen. Siehe db4o reference .

Aber ehrlich gesagt: Der gleiche Prozess in einem RDBMS ist auch kompliziert, weil Sie Constraint-Checks (und möglicherweise Trigger, etc.) deaktivieren müssen, um die Operation tatsächlich auszuführen - vielleicht nicht in dem von Ihnen bereitgestellten Beispiel, aber für die meisten realen Fälle. Schließlich ist die Saitenteilung so einfach, dass es wenig Gewinn gibt.

  

In SQL würde ich einfach die Spalten "first_name" und "second_name" füllen

Ja, mit einer einfachen String-Split-Operation können Sie einfach tun. In einem typischen Refactoring-Szenario strukturieren Sie Objekte jedoch basierend auf großen und komplizierten Regelsätzen, die in SQL möglicherweise nicht einfach ausgedrückt werden können, komplexe Berechnungen oder externe Datenquellen benötigen.

Dazu müssten Sie auch Code schreiben.

Immerhin sehe ich in den beiden Prozessen keinen allzu großen Unterschied. Sie müssen immer mit Live-Daten vorsichtig sein, und Sie werden in beiden Fällen sicher ein Backup machen. Refactoring macht Spaß, aber Beharrlichkeit ist schwierig, daher ist es in jedem Fall eine Herausforderung, sie zu synchronisieren.

    
mnemosyn 10.03.2010 21:03
quelle