Android: aktualizacja wersji DB i dodanie nowej tabeli
Utworzyłem już tabele sqlite dla mojej aplikacji, ale teraz chcę dodać nową tabelę do bazy danych.
Zmieniłem wersję DB jak poniżej
private static final int DATABASE_VERSION = 2;
I dodano łańcuch do tworzenia tabeli
private static final String DATABASE_CREATE_color =
"CREATE TABLE IF NOT EXISTS files(color text, incident_id text)";
onCreate
i onUpgrade
Jak poniżej:
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE_incident);
database.execSQL(DATABASE_CREATE_audio);
database.execSQL(DATABASE_CREATE_video);
database.execSQL(DATABASE_CREATE_image);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//drop table and add new tables when version 2 released.
db.execSQL(DATABASE_CREATE_color);
}
Ale z jakiegoś powodu nowa tabela nie jest tworzona. Co robię źle?
5 answers
1. O OnCreate () i onUpgrade()
onCreate(..)
jest wywoływany, gdy aplikacja jest świeżo zainstalowana. onUpgrade
jest wywoływany za każdym razem, gdy aplikacja jest aktualizowana i uruchamiana, a wersja bazy danych nie jest taka sama.
2. Zwiększenie wersji db
Potrzebujesz konstruktora typu:
MyOpenHelper(Context context) {
super(context, "dbname", null, 2); // 2 is the database version
}
Ważne: zwiększenie samej wersji aplikacji nie wystarczy do wywołania onUpgrade
!
3. Nie zapomnij o nowym użytkownicy!
Nie zapomnij dodać
database.execSQL(DATABASE_CREATE_color);
Do metody onCreate() lub nowo zainstalowanych aplikacji będzie brakowało tabeli.
4. Jak radzić sobie z wieloma zmianami w bazie danych w czasie
Gdy masz kolejne aktualizacje aplikacji, z których kilka ma uaktualnienia bazy danych, chcesz mieć pewność, aby sprawdzić oldVersion
:
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch(oldVersion) {
case 1:
db.execSQL(DATABASE_CREATE_color);
// we want both updates, so no break statement here...
case 2:
db.execSQL(DATABASE_CREATE_someothertable);
}
}
W ten sposób, gdy użytkownik aktualizuje z wersji 1 do wersji 3, otrzymuje obie aktualizacje. Gdy użytkownik aktualizuje z wersji 2 do 3, po prostu dostają aktualizację wersji 3... W końcu nie możesz liczyć na 100% bazy użytkowników, aby uaktualnić za każdym razem, gdy wydajesz aktualizację. Czasami pomijają update lub 12:)
5. Utrzymywanie numerów wersji pod kontrolą podczas tworzenia
I wreszcie... wywołanie
adb uninstall <yourpackagename>
Całkowicie odinstalowuje aplikację. Po ponownej instalacji masz gwarancję trafienia onCreate
, co zapobiega konieczności zwiększania wersji bazy danych do stratosfery w miarę rozwoju...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-30 21:47:55
Twój kod wygląda poprawnie. Sugeruję, że baza myśli, że jest ulepszona. Jeśli wykonałeś projekt po zwiększeniu numeru wersji, ale przed dodaniem wywołania execSQL
, baza danych na Twoim urządzeniu testowym / emulatorze może już wierzyć, że jest w wersji 2.
Szybkim sposobem, aby to zweryfikować, byłaby zmiana numeru wersji na 3-Jeśli uaktualni się po tym, wiesz, że było to tylko dlatego, że Twoje urządzenie wierzyło, że zostało już zaktualizowane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-15 08:51:13
Możesz użyć metody sqliteopenhelper onUpgrade
. W metodzie onUpgrade otrzymujesz oldVersion jako jeden z parametrów.
W onUpgrade
Użyj switch
, a w każdym z case
Użyj numeru wersji, aby śledzić bieżącą wersję bazy danych.
Najlepiej jest przełączyć się z oldVersion
do newVersion
, zwiększając version
o 1 na raz, a następnie krok po kroku aktualizować bazę danych. Jest to bardzo pomocne, gdy ktoś z bazy danych w wersji 1 aktualizuje aplikację po długim czasie, do wersja korzystająca z bazy danych w wersji 7 i aplikacja zaczyna się zawieszać z powodu pewnych niekompatybilnych zmian.
Następnie aktualizacje w bazie danych będą wykonywane krok po kroku, obejmując wszystkie możliwe przypadki, tj. włączając zmiany w bazie danych wykonane dla każdej nowej wersji i tym samym zapobiegając awarii aplikacji.
Na przykład:
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
String sql = "ALTER TABLE " + TABLE_SECRET + " ADD COLUMN " + "name_of_column_to_be_added" + " INTEGER";
db.execSQL(sql);
break;
case 2:
String sql = "SOME_QUERY";
db.execSQL(sql);
break;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-20 18:10:39
@ Jkschneider ' s answer is right. Istnieje jednak lepsze podejście.
Zapisz potrzebne zmiany w pliku sql dla każdej aktualizacji, jak opisano w linku https://riggaroo.co.za/android-sqlite-database-use-onupgrade-correctly/
From_1_to_2.sql
ALTER TABLE books ADD COLUMN book_rating INTEGER;
From_2_to_3.sql
ALTER TABLE books RENAME TO book_information;
From_3_to_4.sql
ALTER TABLE book_information ADD COLUMN calculated_pages_times_rating INTEGER;
UPDATE book_information SET calculated_pages_times_rating = (book_pages * book_rating) ;
To .pliki sql będą wykonywane w metodzie onUpgrade() zgodnie z wersją baza danych.
DatabaseHelper.java
public class DatabaseHelper extends SQLiteOpenHelper {
private static final int DATABASE_VERSION = 4;
private static final String DATABASE_NAME = "database.db";
private static final String TAG = DatabaseHelper.class.getName();
private static DatabaseHelper mInstance = null;
private final Context context;
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
public static synchronized DatabaseHelper getInstance(Context ctx) {
if (mInstance == null) {
mInstance = new DatabaseHelper(ctx.getApplicationContext());
}
return mInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(BookEntry.SQL_CREATE_BOOK_ENTRY_TABLE);
// The rest of your create scripts go here.
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.e(TAG, "Updating table from " + oldVersion + " to " + newVersion);
// You will not need to modify this unless you need to do some android specific things.
// When upgrading the database, all you need to do is add a file to the assets folder and name it:
// from_1_to_2.sql with the version that you are upgrading to as the last version.
try {
for (int i = oldVersion; i < newVersion; ++i) {
String migrationName = String.format("from_%d_to_%d.sql", i, (i + 1));
Log.d(TAG, "Looking for migration file: " + migrationName);
readAndExecuteSQLScript(db, context, migrationName);
}
} catch (Exception exception) {
Log.e(TAG, "Exception running upgrade script:", exception);
}
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
private void readAndExecuteSQLScript(SQLiteDatabase db, Context ctx, String fileName) {
if (TextUtils.isEmpty(fileName)) {
Log.d(TAG, "SQL script file name is empty");
return;
}
Log.d(TAG, "Script found. Executing...");
AssetManager assetManager = ctx.getAssets();
BufferedReader reader = null;
try {
InputStream is = assetManager.open(fileName);
InputStreamReader isr = new InputStreamReader(is);
reader = new BufferedReader(isr);
executeSQLScript(db, reader);
} catch (IOException e) {
Log.e(TAG, "IOException:", e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
Log.e(TAG, "IOException:", e);
}
}
}
}
private void executeSQLScript(SQLiteDatabase db, BufferedReader reader) throws IOException {
String line;
StringBuilder statement = new StringBuilder();
while ((line = reader.readLine()) != null) {
statement.append(line);
statement.append("\n");
if (line.endsWith(";")) {
db.execSQL(statement.toString());
statement = new StringBuilder();
}
}
}
}
Przykładowy projekt znajduje się również w tym samym linku: https://github.com/riggaroo/AndroidDatabaseUpgrades
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-23 21:25:17
Obsługa wersji baz danych jest bardzo ważną częścią tworzenia aplikacji. Zakładam, że masz już klasę AppDbHelper rozszerzającą SQLiteOpenHelper
. Po jej rozszerzeniu należy zaimplementować metodę onCreate
i onUpgrade
.
-
Gdy
onCreate
ionUpgrade
metody nazywane-
onCreate
wywołane po ponownym zainstalowaniu aplikacji. -
onUpgrade
wywołane po aktualizacji aplikacji.
-
-
Organizowanie wersji baz danych Zarządzam wersjami metodami klasowymi. Utwórz implementacja migracji interfejsu. Np. dla pierwszej wersji create
MigrationV1
Klasa, drugiej wersji createMigrationV1ToV2
(są to moje nazewnictwo)
public interface Migration {
void run(SQLiteDatabase db);//create tables, alter tables
}
Przykład migracji:
public class MigrationV1ToV2 implements Migration{
public void run(SQLiteDatabase db){
//create new tables
//alter existing tables(add column, add/remove constraint)
//etc.
}
}
- używanie klas migracji
onCreate
: ponieważ onCreate
zostanie wywołana podczas świeżo zainstalowanej aplikacji, musimy również wykonać wszystkie migracje (aktualizacje wersji bazy danych). Więc onCreate
will wygląda tak:
public void onCreate(SQLiteDatabase db){
Migration mV1=new MigrationV1();
//put your first database schema in this class
mV1.run(db);
Migration mV1ToV2=new MigrationV1ToV2();
mV1ToV2.run(db);
//other migration if any
}
onUpgrade
: metoda ta zostanie wywołana, gdy aplikacja jest już zainstalowana i jest aktualizowana do nowej wersji aplikacji. Jeśli aplikacja zawiera jakiekolwiek zmiany w bazie danych, to wszystkie zmiany w bazie danych należy umieścić w nowej klasie migracji i wersji bazy danych increment.
Na przykład, powiedzmy, że użytkownik ma zainstalowaną aplikację, która ma bazę danych w wersji 1, a teraz Wersja bazy danych jest aktualizowana do wersji 2(wszystkie aktualizacje schematu przechowywane w MigrationV1ToV2
). Teraz po aktualizacji aplikacji, musimy uaktualnić bazę danych, stosując zmiany schematu bazy danych w MigrationV1ToV2
, Jak to:
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
//means old version is 1
Migration migration = new MigrationV1ToV2();
migration.run(db);
}
if (oldVersion < 3) {
//means old version is 2
}
}
Uwaga: wszystkie uaktualnienia (wymienione w
onUpgrade
) w schemacie bazy danych powinny być wykonywane wonCreate
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-26 17:16:40