2016-10-10 12 views
7

Mam aplikację na Androida, która korzysta z bazy danych SQLite i Active Android jako ORM. Przy każdej aktualizacji aplikacji muszę wysłać moją bazę danych z nowymi/zaktualizowanymi danymi. To, co robiłemAndroid SQLite: zastąp istniejącą bazę danych nową lub użyj skryptów migracji

  1. Mam my_app.db bazy
  2. ja wprowadzania zmian w wierszach, stoły, itp z my_app.db
  3. I zapisać zmodyfikowany my_app.db jak my_app_v2.db (i tak dalej)
  4. wymienić my_app.db plik w folderze aktywów z my_app_v2.db i ustawić go jako domyślny bazy
  5. skompilować i uruchomić program za pomocą nowo utworzonego my_app_v2.db

Więc gdy użytkownik pobiera aplikację, zostanie ona przy użyciu my_app_v2.db z nową zawartością.

Wiem, że aktywny Android supports migration scripts, ale przy każdej aktualizacji bazy danych muszę dodać/zaktualizować około 2000 rekordów. Tak więc dla każdej aktualizacji bazy danych potrzebowałbym skryptu migracji z 2000+ instrukcjami wstawiania/aktualizacji, oznacza to, że dla 3+ kolejnych aktualizacji aplikacja musiałaby wykonać około 6000 instrukcji.

Chcę wiedzieć, czy moje podejście polegające na zastąpieniu całej bazy danych nową jest złą praktyką, a skrypty migracji powinny być preferowane.

+0

dla Insert/zapytania uaktualnienia są przechodzącą oddzielne kwerendy lub z wykorzystaniem transakcji dla zapytań ?? – PN10

+0

Jak już powiedziałem, wysyłam aplikację z nową bazą danych z całą zawartością aktualizacji, dlatego nie używam kwerendy wstawiania/aktualizacji do aktualizacji bazy danych w metodzie onUpdate(). – regmoraes

+0

Możliwy duplikat http://stackoverflow.com/questions/19793004/android-sqlite-database-why-drop-table-and-recreate-on-upgrade – Tushar

Odpowiedz

5

Nie trzeba robić rzeczy, że zmiana nazwy (lub coś)

wystarczy zmienić wersję bazy danych i napisać polecenie SQL, aby zmienić swoją poprzednią tabelę migracji z wersji A do B.

Spójrz na ten link:

Android: upgrading DB version and adding new table

+0

Mój "problem" polega na tym, że chcę przeprowadzić migrację bazy danych za pomocą nowych/zaktualizowanych wierszy, a nie tylko utworzyć/zmienić tabelę. Co więcej, jeśli zastąpię starą bazę danych (przestarzałą zawartość i wersję 1) z folderu zasobów inną bazą danych (taką samą jak stara, nowa/zaktualizowana zawartość i wersja 2), to będzie działać? – regmoraes

+0

Możesz zmienić swoje colmun db, a nawet wiersze. Wystarczy napisać polecenie update sql. Cokolwiek to jest. Musisz usunąć wszystkie stare wiersze? Zrób to. Musisz keeep stare i dodać kilka innych wierszy? Po prostu wpisz polecenie sql, aby to zrobić. Cokolwiek możesz zrobić za pomocą polecenia sql, możesz zrobić w sesji aktualizacji;) –

+0

Podczas czytania twojego pytania umieściłeś plik db na folderze zasobów, którego nie potrzebujesz, a jest to niewłaściwa praktyka, ponieważ wtedy onUpgrade nie będzie działać dla ciebie. Następnie musisz sam sobie poradzić z aktualizacją DB. Musisz to zrobić ręcznie przed otwarciem połączenia z db. –

0

nie jestem pewien, że można zastosować tę drogę w swojej aplikacji, ale tutaj jest to, co robię, aby pobrać nowe dane z innej bazy danych.

Do moich aplikacji używam systemu synchronizacji, który codziennie sprawdza, czy nowa baza danych jest dostępna w GoogleDrive (w przypadku, gdy użytkownik korzysta z różnych urządzeń).

Kiedy nowa kopia zapasowa baza danych jest dostępna (czyli muszę pobierać dane dla tego urządzenia), wrócę kopię zapasową bazy danych i dołączyć go do istniejącej używając:

attach database database/path as new_db 

Potem wystarczy wykonać to polecenie dla każdego stołu w celu zaktualizowania istniejącej bazy danych z ewidencji z jednej I pobierane:

INSERT OR REPLACE INTO table SELECT * FROM retrieved_database.table 

oczywiście będzie on zastąpić wszystkie istniejące dane, ale w ten sposób ja również obsługiwać rekordy, które zostały zmodyfikowane. Ta metoda pozwala na całkowite zastąpienie istniejącej bazy danych, po prostu sprawdzam integralność na końcu, aby upewnić się, że wszystko jest w porządku.

Ta metoda jest dla mnie dobra, ponieważ mam kilka tabel i dane są lekkie, może to być zły pomysł na ciężkie bazy danych.

0

W moim projekcie użyłem jak ten

public class DatabaseHelper extends SQLiteOpenHelper { 

private final static String TAG = DatabaseHelper.class.getSimpleName(); 
private static DatabaseHelper sInstance; 
private Context mContext; 
private static final String DATABASE_NAME = "xxxx"; 
private static final String DATABASE_NAME_OLD = "xxxx_old"; 
private static final int DATABASE_VERSION = 12; 
private String pathToSaveDBFile, absolutepathToSaveDBFile; 
private SQLiteDatabase db; 
private Cursor cursor; 



public static synchronized DatabaseHelper getInstance(Context mContext) { 
    if (sInstance == null) { 
     sInstance = new DatabaseHelper(mContext); 
    } 
    return sInstance; 
} 

/** 
* initialization constructor 
* 
* @param context 
*/ 

private DatabaseHelper(Context context) { 
    super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    this.mContext = context; 
    pathToSaveDBFile = new StringBuffer(context.getFilesDir().getAbsolutePath()).append("/").append(DATABASE_NAME).toString(); 
    absolutepathToSaveDBFile = new StringBuffer(context.getFilesDir().getAbsolutePath()).append("/").append(DATABASE_NAME_OLD).toString(); 

} 

/** 
* prepare database related process 
* 
* @throws IOException 
*/ 
public void prepareDatabase() throws IOException { 
    //boolean dbExist = checkDataBase(); 
    if (checkDataBase()) { 
     Log.d(TAG, "Database exists."); 
    //   int currentDBVersion = getVersionId(); 
     if (DATABASE_VERSION > getVersionId()) { 
      Log.d(TAG, "Database version is higher than old."); 
        if (renameDatabase()) { 
         Log.d(TAG, "renameDatabase() "); 

         try { 
          if (copyDataBase()) { 


            deleteDb(); 
             setVersionId(DATABASE_VERSION); 
           } 




        } catch (Exception e) { 
         Log.e(TAG, e.getMessage()); 
        } 
       } 


     } 
    } else { 
     try { 
      /// copy db 
      copyDataBase(); 
     } catch (Exception e) { 
      Log.e(TAG, e.getMessage()); 
     } 
    } 
} 


/** 
* db exist or not? 
* 
* @return db checked status 
*/ 
private boolean checkDataBase() { 
    Log.d(TAG, "checkDataBase()"); 
    boolean checkDB = false; 
    try { 
     File file = new File(pathToSaveDBFile); 
     checkDB = file.exists(); 
    } catch (SQLiteException e) { 
     Log.d(TAG, e.getMessage()); 
    } 
    Log.d(TAG, "checkDataBase: " + checkDB); 
    return checkDB; 
} 

/** 
* db copying 
* 
* @return db copy status 
*/ 
private Boolean copyDataBase() { 
    try { 
     Log.d(TAG, "copyDataBase()"); 
     OutputStream os = new FileOutputStream(pathToSaveDBFile); 
     InputStream is = mContext.getAssets().open("db/" + DATABASE_NAME); 
     byte[] buffer = new byte[1024]; 
     int length; 
     while ((length = is.read(buffer)) > 0) { 
      os.write(buffer, 0, length); 
     } 
     is.close(); 
     os.flush(); 
     os.close(); 
     return true; 
    } catch (IOException e) { 
     e.getMessage(); 
     return false; 
    } 

} 

/** 
* db renaming 
* 
* @return boolean status 
*/ 
private boolean renameDatabase() { 
    try { 
     Log.d(TAG, "renameDatabase: "); 
     File from = new File(pathToSaveDBFile); 
     File to = new File(absolutepathToSaveDBFile); 
     if (from.renameTo(to)) { 
      return true; 
     } 
     return false; 

    } catch (Exception e) { 
     e.getMessage(); 
     return false; 
    } 

} 

/** 
* 
* 
* @return boolen status 
*/ 
private boolean revertBack_to_OlderName() { 
    try { 
     Log.d(TAG, "renameDatabase: "); 
     File from = new File(absolutepathToSaveDBFile); 
     File to = new File(pathToSaveDBFile); 
     if (from.renameTo(to)) { 
      return true; 
     } 
     return false; 

    } catch (Exception e) { 
     e.getMessage(); 
     return false; 
    } 

} 

/** 
* db deletion 
* 
* delete db 
*/ 
public void deleteDb() { 
    File file = new File(absolutepathToSaveDBFile); 
    if (file.exists()) { 
     file.delete(); 
     Log.d(TAG, "Database deleted."); 
    } 
} 


@Override 
public void onCreate(SQLiteDatabase sqLiteDatabase) { 

} 

@Override 
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { 

} 

@Override 
public synchronized void close() { 
    db.close(); 
    super.close(); 
} 



/** 
* get db version info 
* 
* @return version no 
*/ 
private int getVersionId() { 
    try { 
     db = SQLiteDatabase.openDatabase(pathToSaveDBFile, null, SQLiteDatabase.OPEN_READONLY); 
     String query = "SELECT " + AS_DB_VERSION_NUMBER + " FROM " + AS_DB_VERSION_TABLE; 
     cursor = db.rawQuery(query, null); 
     cursor.moveToFirst(); 
     int v = cursor.getInt(0); 
     cursor.close(); 
     close(); 
     return v; 
    } catch (SQLiteException e) { 
     e.getMessage(); 
     return 0; 
    } 


} 

/** 
* set db version no to 
* @param version 
* 
* @return status 
*/ 
private boolean setVersionId(int version) { 
    try { 
     db = SQLiteDatabase.openDatabase(pathToSaveDBFile, null, SQLiteDatabase.OPEN_READWRITE); 
     ContentValues values = new ContentValues(); 
     values.put(AS_DB_VERSION_NUMBER, version); 
     db.update(AS_DB_VERSION_NUMBER, values, AS_DB_VERSION_ID + " = 1", null); 
     close(); 
     return true; 
    } catch (SQLiteException e) { 
     e.getMessage(); 
     return false; 
    } 
    } 
} 

można użyć tych kod w swoim konkursie

Powiązane problemy