Domanda

Una cosa che ho sempre trovato molto confuso su come utilizzare un database ad oggetti come db4o è come si si suppone per gestire migrazioni complesse che normalmente essere gestiti da SQL / PL-SQL.

Per esempio Immagina di avere una tabella di un database relazionale chiamato my_users. In origine si era una colonna chiamata "FULL_NAME", ora che il software sia in V2 si desidera rimuovere questa colonna, dividere i nomi completi su uno spazio vuoto e mettere la prima parte di una colonna denominata "first_name" e il secondo in una colonna nome cognome. In SQL Vorrei semplicemente popolare i "first_name" e colonne "second_name", quindi rimuovere la colonna originale denominata "FULL_NAME".

Come potrei fare questo in qualcosa di simile db4o? Faccio a scrivere un programma Java che gli script di guardare tutti gli oggetti di User.class, impostando FULL_NAME per nulla durante l'impostazione first_name e cognome? Quando faccio le mie prossime svn commit non ci sarà alcun campo / fagiolo-proprietà corrispondente a FULL_NAME, questo sarebbe un problema? Sembra come se usarlo in un'applicazione di produzione in cui i miei cambiamenti "schema" Vorrei scrivere uno script per la migrazione dei dati dalla versione x alla versione x + 1 e poi nella versione x + 2 in realtà rimuovere le proprietà che sto cercando di sbarazzarsi di per la versione x + 1 come non riesco a scrivere uno script Java per modificare le proprietà che non sono più parte del mio tipo.

Sembra che parte del problema è che un RDBMS risolve Quale oggetto si fa riferimento in base a un nome di stringa basata insensibile semplice caso, in un linguaggio come digitazione Java è più complicato di così, non si può fare riferimento a una proprietà se il getter / setter / campo non sono un membro della classe caricata in fase di esecuzione in modo essenzialmente bisogno di avere 2 versioni del codice nello stesso script (hmm, classloader personalizzati suonano come un dolore), avere la nuova versione della classe conservati appartenere ad un altro pacchetto (suona disordinato), oppure utilizzare la versione x + 1 x 2 + strategia che ho citato (richiede molto di più di pianificazione). Forse c'è qualche soluzione ovvia ho mai spigolato dai documenti db4o.

Tutte le idee? Speriamo che questo fa un certo senso.

È stato utile?

Soluzione

In primo luogo, db4o gestisce il 'semplice' scenari come l'aggiunta o la rimozione di un campo automaticamente . Quando si aggiunge il campo, tutti gli oggetti esistenti hanno il valore di default memorizzato. Quando si rimuove un campo, i dati di oggetto esistente è ancora in banca dati e si può ancora accedervi. Rinominare campo ecc sono speciale '-chiamate refactoring' .

Ora lo scenario si potrebbe fare qualcosa di simile:

  1. Rimuovere il campo 'full_name', aggiungi 'first_name' i nuovi campi e 'second_name'
  2. iterare su tutte le esigenze degli Address'-oggetti
  3. L'accesso al vecchio campo attraverso il 'StoredClass'-API
  4. Split, modificare, aggiornare il valore ecc. Impostare i nuovi valori del nuovo campo e memorizzare l'oggetto.

Supponiamo che abbiamo un 'Address' classe. Il campo 'full_name' è stato rimosso. Ora abbiamo wan't per copiarlo nella 'cognome' e 'il cognome'. Poi si potrebbe andare in questo modo (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);
    }

Come lei ha suggerito, si potrebbe scrivere la migrazione del codice per ogni versione-urto. E 'un campo non fa parte della classe più, è necessario accedere con 'StoredField'-API come sopra.

È possibile ottenere un elenco di tutte le classi 'archiviati' con ObjectContainer.ext().storedClasses(). Con StoredClass.getStoredFields() è possibile ottenere un elenco di tutti i campi di negozio, non mather è il campo non esiste più nella tua classe. Se una classe non esiste più, è ancora possibile ottenere gli oggetti e accedervi tramite 'GenericObject' classe.

Aggiornamento:. Per gli scenari complexer in cui una banca dati ha bisogno di migrare su più-version-passaggi

Per esempio, nella versione v3 l'indirizzo-oggetto sembra completamente diverso. Così la 'migrazione-script' per v1 a v2 non ha ottenuto i campi più richiede (nome e cognome nel mio esempio). Penso che ci sono molteplici possibilità per la gestione di questo.

  1. (Supponendo Java per questa idea. Certo, c'è un equivalente in .NET). Si potrebbe fare la migrazione passo un Groovy-script . Così ogni che ogni script non interferisce con un altro. Poi si definiscono 'classi' le classi necessarie per la migrazione lì. Così ogni migrazione ha le sue migrazione-classi. Con alias voi legherebbe i tuoi groove-migration-classi per l'attuale java-classi.
  2. Creazione di refactoring-classi per scenari complessi. Anche legare questo classi con alias .

Altri suggerimenti

mi sto prendendo un po 'di un colpo selvaggio qui, perché non ho refactoring troppi dati nella mia vita.

Stai facendo un confronto strano: se si voleva 'hot-migrate' il db, si sarebbe probabilmente dovete fare la x+1, approccio x+2 delle versioni hai descritto, ma io non so davvero - I wouldn' t sapere come fare questo con SQL o dal momento che non sono un esperto di db.

Se la migrazione 'freddo', tuttavia, si può solo farlo in un solo passo da un'istanza di un nuovo oggetto dai vecchi dati, memorizzare il nuovo oggetto, eliminare il vecchio oggetto per ogni oggetto nel negozio. Vedere db4o riferimento .

Ma onestamente: lo stesso processo in un RDBMS è complicato, anche perché si dovrà disattivazione avviene controlli di vincolo (e possibilmente trigger, ecc) per eseguire effettivamente l'operazione - forse non nell'esempio che hai fornito, ma per la maggior parte dei casi reali. Dopo tutto, la spaccatura stringa è così facile che ci sarà poco guadagno.

  

In SQL Vorrei semplicemente popolare "first_name" e "second_name" colonne

Sì, con un semplice operazione stringa divisa, è possibile semplicemente farlo. Ma gli oggetti in un tipico scenario di refactoring, si sta ri-strutturazione basati sui set di grandi e complicate di regole che non possono essere facilmente espresse in SQL, potrebbe essere necessario calcolo complesso, o fonti di dati esterne.

Per fare questo, dovreste scrivere codice, anche.

Dopo tutto, non vedo troppa differenza nei due processi. Sarete sempre stare attenti con dati in tempo reale, e sicuramente si farà fare un backup in entrambi i casi. Refactoring è divertente, ma la persistenza è difficile quindi la sincronizzazione è una sfida, in ogni caso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top