Frage

Eine Sache, die ich immer wieder sehr verwirrend gefunden haben, über eine Objektdatenbank mit wie db4o ist, wie Sie sollen komplex Migrationen behandeln, die normalerweise von SQL / PL-SQL behandelt werden würden.

Zum Beispiel vorstellen, dass Sie in einer relationalen Datenbank eine Tabelle hatten my_users genannt. Ursprünglich hatte man eine Spalte „full_name“ genannt, jetzt, dass Ihre Software in V2 Sie diese Spalte entfernen möchten, teilen Sie die vollständigen Namen auf einem leeren Raum und den ersten Teil in einer Spalte „first_name“ genannt und die zweite in einer Spalte genannt last_name. In SQL würde ich einfach bevölkern die „first_name“ und „second_name“ Spalten dann die ursprüngliche Spalte entfernen Namen „full_name“.

Wie würde ich tun dies in so etwas wie db4o? Muss ich ein Java-Programm schreiben, die Skripte alle Objekte User.class aufzublicken, full_name auf null einstellen, während first_name Einstellung und last_name? Wenn ich meine nächste SVN tue begehen wird es kein Feld / bean-Eigenschaft sein, FULL_NAME entsprechenden wäre dies ein Problem sein? Es scheint, als ob es in einer Produktionsanwendung zu verwenden, wo meine „Schema“ Änderungen, die ich ein Skript schreiben möchten Daten von Version zu x auf Version x + 1 und dann in der Version x + 2 entfernt tatsächlich die Eigenschaften Ich versuche, zu migrieren befreien Sie sich von der Version erhalten x + 1, da ich nicht eine Java-Skript Eigenschaften modifizieren schreiben kann, die länger Teil meiner Art nicht sind.

Es scheint, dass ein Teil des Problems ist, dass ein RDBMS löst welches Objekt Sie basiert auf einem einfachen Fall unempfindlich stringbasierte Namen beziehen, in einer Sprache wie Java Typisierung als dies komplizierter ist, können Sie nicht auf eine Eigenschaft verweisen wenn die Getter / Setter / Feld kein Mitglied der Klasse ist zur Laufzeit geladen, so dass Sie im wesentlichen zwei Versionen des Codes im selben Skript haben müssen (hmm, benutzerdefinierte Classloader wie ein Schmerz klingen), haben Sie die neue Version der Klasse zu einem anderen Paket gespeichert ist, gehört (chaotisch klingt), oder die ich erwähnte Version x + 1 x + 2 Strategie verwenden (erfordert viel mehr Planung). Vielleicht gibt es eine offensichtliche Lösung, die ich nie aus den db4o Dokumenten zu entnehmen.

Irgendwelche Ideen? Hoffentlich macht einen Sinn.

War es hilfreich?

Lösung

Als erstes db4o die 'einfachen' Szenarien wie das Hinzufügen oder ein Feld automatisch entfernen. Wenn Sie das Feld hinzufügen, wird alles vorhandenes Objekt hat den gespeicherten Standardwert. Wenn Sie ein Feld entfernen, werden die Daten von bestehenden Objekt noch in der Datenbank und Sie können es immer noch zugreifen. Umbenennen Feld etc sind Sonder ‚refactoring'-Anrufe .

Jetzt Ihr Szenario würden Sie so etwas tun:

  1. Entfernen Sie das Feld 'full_name', fügen Sie die neuen Felder 'first_name' und 'second_name'
  2. iterieren alle ‚Address'-Objekte
  3. Rufen Sie das alte Feld über den ‚StoredClass'-API
  4. Split, zu ändern, aktualisieren usw. den Wert. Legen Sie die neuen Werte auf dem neuen Feld und speichern Sie das Objekt aus.

Nehmen wir an, wir ‚Address'-Klasse. Das ‚full_name‘ Feld wird entfernt. Jetzt wan't wir es auf den ‚Vornamen‘ zu kopieren und ‚Namen‘. Dann könnte es so (Java) gehen:

    ObjectSet<Address> addresses = db.query(Address.class);
    StoredField metaInfoOfField = db.ext().storedClass(Address.class).storedField("full_name", String.class);
    for (Address address : addresses) {
        String fullName = (String)metaInfoOfField.get(address);
        String[] splitName = fullName.split(" ");
        address.setFirstname(splitName[0]);
        address.setSurname(splitName[1]);
        db.store(address);
    }

Wie Sie vorgeschlagen, würden Sie migrations Code für jede Version den Höckern schreiben. Es ist ein Feld nicht Teil Ihrer Klasse mehr, haben Sie für den Zugriff mit ‚StoredField'-API wie oben.

Sie können eine Liste aller ‚gespeichert‘ Klassen mit ObjectContainer.ext().storedClasses() bekommen. Mit StoredClass.getStoredFields() Sie eine Liste aller Speicher Felder bekommen, ist: Egal, das Feld nicht mehr in der Klasse nicht vorhanden ist. Wenn eine Klasse nicht mehr existiert, können Sie immer noch die Objekte bekommen und es über ‚GenericObject'-Klasse zugreifen.

Update:. Für komplexeren Szenarien, in denen eine Datenbank mit mehreren Versionsschritte migriert muss

Zum Beispiel in der Version v3 das Adresse-Objekt sieht ganz anders aus. So ist die ‚Migration-Skript‘ für v1 v2 hat nicht die Felder bekommt mehr erfordert (Vornamen und Nachnamen in meinem Beispiel). Ich denke, es gibt mehrere Möglichkeiten, die diese für die Handhabung.

  1. (Unter der Annahme, Java für diese Idee. Sicherlich gibt es eine Entsprechung in .NET). Sie könnten die Migration für Schritt eines Groovy-Skript machen. Also jeder, dass jedes Skript nicht stört mit einem anderen. Dazu gibt es ‚Klassen‘ die benötigten Klassen für die Migration definieren. So wird jede Migration hat seine eigene Migration Klassen. Mit Aliase binden würde Ihre groovy-Migration-Klassen zu den eigentlichen Java-Klassen.
  2. Erstellen von Refactoring-Klassen für komplexe Szenarien. Auch binden diese Klassen mit Aliase .

Andere Tipps

Ich bin hier ein bisschen von einem wilden Schuss zu nehmen, weil ich nicht zu viele Daten in meinem Leben Refactoring haben.

Sie sind ein seltsamen Vergleich machen: Wenn Sie die db zu ‚hot-Migrate‘ wollen, dann würden Sie wahrscheinlich den x+1, x+2 Versionierung Ansatz zu tun haben, wissen Sie beschrieben, aber ich weiß nicht wirklich - ich wouldn‘ t wissen, wie dies entweder mit SQL zu tun, da ich bin kein Experte db.

Wenn Sie ‚kalt‘ migrieren, aber könnten Sie tun es nur in einem Schritt durch ein neues Objekt aus den alten Daten instanziiert wird, speichern Sie das neue Objekt, löschen Sie das alte Objekt für jedes Objekt im Speicher. Siehe db4o Referenz .

Aber ehrlich gesagt: der gleiche Prozess in einem RDBMS kompliziert ist, auch, weil Sie haben zu deaktivieren Einschränkung überprüft (und möglicherweise Auslöser usw.), um den Vorgang durchführen - vielleicht nicht in dem Beispiel, das Sie zur Verfügung gestellt, aber für die meisten realen Fällen. Immerhin ist der String Split so leicht, dass es wenig Gewinn.

  

In SQL würde ich einfach bevölkern "first_name" und "second_name" Spalten

Ja, mit einem einfach string Split-Betrieb, können Sie einfach tun. Aber in einem typischen Refactoring Szenario Sie erneut Strukturierung basierte Objekte auf große und komplizierte Sätze von Regeln, die nicht könnte leicht in SQL ausgedrückt werden, könnten komplexe Berechnung benötigen oder externen Datenquellen.

Um das zu tun, dann würden Sie haben den Code zu schreiben, zu.

Schließlich habe ich nicht zu viel Unterschied in den beiden Prozessen sehen. Sie müssen immer mit Live-Daten vorsichtig sein, und Sie werden sicherlich eine Sicherung in beiden Fällen machen. Refactoring ist Spaß, aber Ausdauer ist schwierig, so dass es zu synchronisieren, ist eine Herausforderung, auf jeden Fall.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top