Confusione: come si comporta SQLiteOpenHelper onUpgrade ()? E insieme all’importazione di un vecchio backup del database?

supponiamo di avere una tabella di database test_table con 2 colonne e uno script di creazione corrispondente in SQLiteOpenHelper:

DB_VERSION = 1: public void onCreate(SQLiteDatabase db) { db.execSql("CREATE table test_table (COL_A, COL_B); } 

Questa è la versione iniziale dell’app 1, che è pubblicata nel Play Store.

Dopo un po ‘c’è un aggiornamento per l’app e il database utilizzato. Immagino che la class SQLiteOpenHelper debba essere adattata in questo modo:

 DB_VERSION = 2: public void onCreate(SQLiteDatabase db) { db.execSql("CREATE table test_table (COL_A, COL_B, COL_C)"); } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSql("ALTER TABLE test_table ADD Column COL_C"); } 

Dopo qualche tempo, un altro aggiornamento dell’app:

 DB_VERSION = 3: public void onCreate(SQLiteDatabase db) { db.execSql("CREATE table test_table (COL_A, COL_B, COL_C, COL_D)"); } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSql("ALTER TABLE test_table ADD Column COL_D"); } 

-> Questo è il posto dove ho bisogno di consigli. Se l’utente installa la versione 1 dell’app, ha le colonne A e B. Se poi aggiorna la versione 2, onUpgrade scatta e aggiunge una colonna C. Nuovi utenti che installano da zero ottengono le 3 colonne tramite l’istruzione create. Se l’utente si aggiorna alla versione 3, suUpgrade si triggers nuovamente e viene aggiunta una colonna D. Ma COSA SE l’utente installa la versione 1 dell’app, quindi salta l’aggiornamento della versione 2 e aggiorna la versione 3? Poi avrebbe perso il

 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSql("ALTER TABLE test_table ADD Column COL_C"); } 

parte e solo

 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSql("ALTER TABLE test_table ADD Column COL_D"); } 

sarebbe chiamato, che porta a una tabella test_table (COL_A, COL_B, COL_D) ??

Qual è il modo corretto di gestire gli aggiornamenti del database di un’app live, quindi l’utente non perde i suoi dati? Dovete controllare tutte le possibili (vecchie) versioni nel metodo onUpgrade () ed eseguire diverse istruzioni alter tabelle basate su quella versione?

Ti sto chiedendo perché nella mia app l’utente ha la possibilità di esportare e importare i dati, che non è altro che l’esportazione: copia tutto il database e importa: sostituisci il database dell’app con il database delle copie di backup.

Cosa succede se l’utente ha la versione 1 dell’app, esporta il database, aggiorna l’app (nuova struttura del database) e importa il backup della versione 1 precedente? -> Come si comporta SQLiteOpenHelper? -> Qual è il modo corretto di gestire gli aggiornamenti db insieme alla funzionalità di importazione / esportazione?

Qual è il modo corretto di gestire gli aggiornamenti del database di un’app live, quindi l’utente non perde i suoi dati? Dovete controllare tutte le possibili (vecchie) versioni nel metodo onUpgrade () ed eseguire diverse istruzioni alter tabelle basate su quella versione?

In generale, sì.

Un approccio comune a questo è quello di fare aggiornamenti per coppie:

 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if (oldVersion<2) { // do upgrade from 1 to 2 } if (oldVersion<3) { // do upgrade from 2 to 3, which will also cover 1->3, // since you just upgraded 1->2 } // and so on } 

Questo equivale approssimativamente alle migrazioni di Rails, per esempio.

Cosa succede se l’utente ha la versione 1 dell’app, esporta il database, aggiorna l’app (nuova struttura del database) e importa il backup della versione 1 precedente? -> Come si comporta SQLiteOpenHelper?

Se “copia tutto il database”, intendi letteralmente una copia di file completa del file di database SQLite, quindi quando SQLiteOpenHelper va ad aprire il backup ripristinato, il database avrà la versione precedente dello schema e passerà attraverso onUpgrade() come normale.

Qual è il modo corretto di gestire gli aggiornamenti db insieme alla funzionalità di importazione / esportazione?

Sospetto che la risposta sia: effettuare il backup copiando l’intero file o anche organizzare il backup e il ripristino della versione dello schema, che è ansible ottenere chiamando getVersion() su un object SQLiteDatabase . Detto questo, non ho affrontato molto questo scenario e potrebbero esserci più problemi a cui non penso.

sotto il codice di psuedo mostra l’aggiornamento incrementale

 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { switch(oldVersion) { case 2: //upgrade logic from version 2 to 3 case 3: //upgrade logic from version 3 to 4 case 4: //upgrade logic from version 4 to 5 break; default: throw new IllegalStateException( "onUpgrade() with unknown oldVersion" + oldVersion)); } } 

Con l’aggiornamento incrementale intendo: nota la frase break mancante nel caso 2 e 3

Se la vecchia versione è 2 e la nuova versione è 4, la logica aggiornerà il database da 2 a 3 e quindi a 4

se la versione precedente è 3 e la nuova versione è 4, verrà eseguita la logica di aggiornamento per 3 o 4

continua ad aggiungere nuovi casi per ogni nuovo aggiornamento della versione del database che farà le modifiche incrementali

ho il sospetto che tu possa anche creare una nuova tabella con tutte le colonne di cui hai bisogno

CREATE TABLE new_test_table (COL_A, COL_B, COL_C,COL_D);

copia i dati dalla vecchia tabella alla nuova

INSERT INTO new_test_table SELECT * FROM test_table;

rilascia la vecchia tabella DROP TABLE test_table;

e rinominare la nuova tabella

ALTER TABLE new_test_table RENAME TO test_table;

quindi insum

 public void onUpgrade(SQLiteDatabase db,int OldVersion,int NewVersion){ db.execSQL("CREATE TABLE new_test_table (COL_A, COL_B, COL_C,COL_D);"+ "INSERT INTO new_test_table SELECT * FROM test_table;"+ "DROP TABLE test_table;"+ "ALTER TABLE new_test_table RENAME TO test_table;");" } 

in questo modo non devi preoccuparti di dataloss o modifiche incrementali

Android-Database-Upgrade-Tutorial mostra la guida completa su come gestisci l’aggiornamento dello schema del tuo database durante il rilascio di nuove versioni di app.

Il tutorial consiste in un’app con 4 versioni, ciascuna contenente un numero diverso di colonne, Diverse versioni dell'applicazione

Questi sono i diversi scenari che si possono affrontare Diversi scenari

Penso che sia troppo tardi per rispondere a questa domanda, ma potrebbe aiutare gli altri.

  DB_VERSION = 1: public void onCreate(SQLiteDatabase db) { db.execSql("CREATE table test_table (COL_A, COL_B, COL_C, COL_D, COL_E); } public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { switch (oldVersion) { case 1: db.execSql("ALTER TABLE test_table ADD Column COL_C"); db.execSql("ALTER TABLE test_table ADD Column COL_D"); db.execSql("ALTER TABLE test_table ADD Column COL_E"); break; case 2: db.execSql("ALTER TABLE test_table ADD Column COL_D"); db.execSql("ALTER TABLE test_table ADD Column COL_E"); break; case 3: db.execSql("ALTER TABLE test_table ADD Column COL_E"); break; and so on... } 

Se l’utente installa l’app per la prima volta, riceverà tutte le colonne da onCreate

Se la vecchia versione del database 2 allora il caso 2 aggiunge la colonna C e D.

Se la vecchia versione del database 3 allora il caso 3 aggiunge solo la colonna E

In questo modo non c’è confusione sulla versione del database.