Question

Une chose que j'ai toujours trouvé très confus sur l'utilisation d'une base de données d'objets comme db4o est de savoir comment vous sont censés gérer les migrations complexes qui seraient normalement traitées par SQL / PL-SQL.

Par exemple, imaginez que vous aviez une table dans une base de données relationnelle appelée mes_utilisateurs. A l'origine, vous aviez une colonne nommée « full_name », maintenant que votre logiciel est en V2 que vous souhaitez supprimer cette colonne, diviser le nom complet sur un espace vide et de mettre la première partie dans une colonne nommée « prenom » et la seconde dans une colonne nommé last_name. Dans SQL Je voudrais simplement remplir les « prenom » et colonnes « second_name » puis retirez la colonne originale nommée « full_name ».

Comment puis-je faire quelque chose comme db4o? Est-ce que j'écris un programme Java que les scripts regardant tous les objets de User.class, réglage full_name null lors de la configuration prenom et LAST_NAME? Quand je fais mon prochain svn commit il n'y aura pas de propriété-féverole / correspondant à FULL_NAME, serait-ce un problème? Il semble que l'utiliser dans une application de production où mes modifications « du schéma » Je veux écrire un script pour migrer les données de la version x à la version x + 1, puis dans la version x + 2 supprimer effectivement les propriétés que je suis en train de se débarrasser de la version x + 1 que je ne peux pas écrire un script Java pour modifier les propriétés qui ne font partie de mon type.

Il semble qu'une partie du problème est qu'un SGBDR résout quel objet vous faites référence à partir d'un simple, insensible à la casse nom basée sur la chaîne, dans un langage comme Java frappe est plus compliqué que cela, vous ne pouvez pas se référer à une propriété si le getter / setter / champ ne sont pas membres de la classe chargé à l'exécution si vous avez besoin essentiellement d'avoir 2 versions de votre code dans le même script (hmm, classloaders personnalisés sonnent comme une douleur), ont la nouvelle version de votre classe stocké appartiennent à un autre paquet (sons désordre), ou utiliser la version x + 1 x + 2 je l'ai mentionné la stratégie (nécessite beaucoup plus de planification). Peut-être il y a une solution évidente, je ne glaner des documents db4o.

Toutes les idées? Espérons que cela fait un certain sens.

Était-ce utile?

La solution

D'abord, db4o gère la 'simple' scénarios comme l'ajout ou la suppression d'un champ automatiquement . Lorsque vous ajoutant le champ, tout objet existant ont la valeur par défaut stockée. Lorsque vous supprimez un champ, les données d'objet existant est encore dans la base de données et vous pouvez toujours y accéder. Etc champ Changement de nom sont spéciale « appels refactoring'-.

Maintenant, votre scénario vous feriez quelque chose comme ceci:

  1. Supprimer le champ 'full_name', ajoutez les nouveaux champs 'prenom' et 'second_name'
  2. sur tous les « itérer objets Address'-
  3. Accédez au champ ancien via le « StoredClass'-API
  4. Split, changement, mettez à jour la valeur etc. Définissez les nouvelles valeurs sur le nouveau champ et stocker l'objet.

Supposons que nous avons un « Address' classe. Le champ « full_name » a été supprimé. Maintenant, nous wan't de le copier à la « prenom » et « nom ». Ensuite, il pourrait se présenter comme suit (Java):

    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);
    }

Comme vous l'avez dit, vous écririez la migration de code pour chaque version bosse. Ce champ ne fait pas partie de votre plus classe, vous devez accéder à « StoredField'-API comme ci-dessus.

Vous pouvez obtenir une liste de toutes les classes « stockées » avec ObjectContainer.ext().storedClasses(). Avec StoredClass.getStoredFields() vous pouvez obtenir une liste de tous les champs de magasin, pas Mather est le champ n'existe plus dans votre classe. Si une classe n'existe plus, vous pouvez toujours obtenir les objets et y accéder via « GenericObject' classe.

Mise à jour:. Pour les scénarios de complexer où une base de données doit migrer sur plusieurs version étapes

Par exemple dans la version v3 l'adresse objet est complètement différente. Ainsi, le pour v1 à v2 « migration-script » n'a pas obtenu les champs plus il a besoin (et prenom Surename dans mon exemple). Je pense qu'il ya plusieurs possibilités pour gérer cela.

  1. (En supposant Java pour cette idée. Certes, il y a un équivalent en .NET). Vous pouvez faire la migration étape Groovy-script. Donc, chaque que chaque script n'interfère pas avec un autre. Ensuite, vous définissez les « classes » de classes nécessaires pour la migration là-bas. Ainsi, chaque migration a ses propres migration classes. Avec alias lierait vos classes-migration-groovy aux java-classes réelles.
  2. Création refactoring classes pour les scénarios complexes. Aussi lier ce cours avec alias .

Autres conseils

Je prends un peu d'un coup de feu sauvage ici, parce que je ne l'ai pas Refactor trop de données dans ma vie.

Vous faites une comparaison étrange: Si vous vouliez «hot-migrate la db, vous auriez probablement faire l'approche x+1, x+2 versioning vous avez décrit, mais je ne sais pas vraiment - je n » t savoir comment faire cela avec SQL soit depuis que je ne suis pas un expert db.

Si vous effectuez la migration « froid », cependant, vous pouvez simplement le faire en une seule étape par instancier un nouvel objet à partir des anciennes données, enregistrer le nouvel objet, supprimez l'ancien objet pour chaque objet dans le magasin. Voir db4o de référence.

Mais honnêtement: le même processus dans un SGBDR est compliqué, aussi, parce que vous devrez désactiver les contrôles de contrainte (et peut-être des déclencheurs, etc.) pour effectuer réellement l'opération - peut-être pas dans l'exemple que vous avez fourni, mais pour la plupart des cas réels. Après tout, la scission de la chaîne est si facile qu'il y aura peu de gain.

  

Dans SQL je remplir simplement "prenom" et colonnes "second_name"

Oui, avec simples opération de division de chaîne, vous pouvez simplement faire. Mais dans un scénario de refactoring typique, vous objets RESTRUCTURATION basés sur de grands ensembles et des règles complexes qui pourraient ne pas être facilement exprimés dans SQL, pourraient avoir besoin des calculs complexes, ou sources de données externes.

Pour ce faire, vous auriez à écrire du code, aussi.

Après tout, je ne vois pas trop de différence dans les deux processus. Vous devez toujours être prudent avec les données en direct, et vous allez certainement faire une sauvegarde dans les deux cas. Refactoring est amusant, mais la persistance est délicate si la synchronisation est un défi dans tous les cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top