Является ли метод onUpgrade когда-либо называемым?

Является onUpgrade метод SQLiteOpenHelper когда-либо вызываемым? Если да, то когда это называется и чем? Если он не вызывается разработчиками, то почему он там? Что на самом деле происходит с этой функцией? Я видел примеры, когда он отбрасывает все таблицы, но в комментарии говорится, что удаление всех таблиц – это не то, что вы должны делать. Какие-либо предложения?

Solutions Collecting From Web of "Является ли метод onUpgrade когда-либо называемым?"

Он вызывается при создании SQLiteOpenHelper с версией, более новой, чем версия открытой базы данных. Что делать, зависит от изменений в базе данных, которые сделаны между старой и новой версиями. Единственный случай, когда вы не отбрасываете измененную таблицу, – это изменение в примечании больше, чем добавленный столбец. Затем вы можете использовать оператор ALTER TABLE, чтобы добавить новый столбец в подпись таблицы.

Для тех из вас, кто хотел бы узнать точный момент, когда onUpgrade() , он находится во время вызова либо getReadableDatabase() либо getWriteableDatabase() .

Тем, кто не ясно, как он запускается, ответ SqLiteOpenHelper : он запускается, когда обновляется версия базы данных, предоставленная конструктору SqLiteOpenHelper . Вот пример

 public class dbSchemaHelper extends SQLiteOpenHelper { private String sql; private final String D_TAG = "FundExpense"; //update this to get onUpgrade() method of sqliteopenhelper class called static final int DB_VERSION = 2; static final String DB_NAME = "fundExpenseManager"; public dbSchemaHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); // TODO Auto-generated constructor stub } 

Теперь … onUpgrade ()

 @Override public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) { sql = "ALTER TABLE " + fundExpenseSchema.Expense.TABLE_NAME + " ADD COLUMN " + fundExpenseSchema.Expense.FUNDID + " INTEGER"; arg0.execSQL(sql); } 

Если вы используете SQLiteOpenHelper, onUpgrade будет вызываться всякий раз, когда вы меняете версию БД. Для этого требуется дополнительное требование. Имя db должно оставаться неизменным.

 Old Version: dbName = "mydb.db" dbVersion = 1 New Version: dbName = "mydb.db" dbVersion = 2 

В onCreate поставщика контента вы создаете экземпляр SQLiteOpenHelper, который принимает эти параметры. Ваша реализация SQLiteOpenHelper будет выглядеть так:

 public static final class MySQLiteOpenHelper extends SQLiteOpenHelper { public MySQLiteOpenHelper(Context context, int dbVersion, String dbName) { super(context, dbName, null, dbVersion); } @Override public void onCreate(SQLiteDatabase db) { //Code to create your db here } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // Code to upgrade your db here } } 

Просмотрев все сообщения и запустив код отладки, мне все еще не было ясно, когда я увижу вызов onUpgrade. Я начал думать, что Android имеет серьезный недостаток.

Информация на этой странице привела меня к моей окончательной резолюции. Спасибо, куча всем участникам!

Это решило это для меня …

 public class DatabaseHelper extends SQLiteOpenHelper { public static String TAG = DatabaseHelper.class.getName(); private static final int DATABASE_VERSION = 42; private static final String DATABASE_NAME = "app_database"; private static final String OLD_TABLE = "old_and_useless"; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion ) { if( newVersion > oldVersion) { Log.d( TAG, "cool! you noticed." ); db.execSQL( "DROP TABLE IF EXISTS " + OLD_TABLE ); // other calls like onCreate if necessary } else { Log.d( TAG, "Hey! didn't you see me?" ); } } public void checkDatabaseVersion() { SQLiteDatabase db = this.getWritableDatabase(); // if the DATABASE_VERSION is newer // onUpgrade is called before this is reached } // other code removed for readability... } 

Это правда, что getWritableDatabase () и getReadableDatabase () приводит к вызову onUpgrade. Я не проверял другие методы, так как они соответствуют требованиям для моих нужд.

Продолжайте читать, кикер идет …

Этот код в моей начальной деятельности просветил меня, когда я наконец понял, что версия db обновлялась во время моей отладки … тьфу!

 DatabaseHelper dbHelper = new DatabaseHelper( this ); dbHelper.checkDatabaseVersion(); 

ПРИМЕЧАНИЕ: вызов конструктора DatabaseHelper обновляет версию db

После вызова конструктора, db был помечен новой версией. Убейте приложение перед вызовом getWritableDatabase () или getReadableDatabase (), и вы находитесь в новой версии. После этого новые исполнения никогда не вызывают метод onUpgrade, пока DATABASE_VERSION не будет снова увеличен. ( Вздох! Теперь это кажется смехотворно очевидным 🙂

Мое предложение состоит в том, чтобы добавить своего рода «checkDatabaseVersion ()» на ранние этапы вашего приложения. Кроме того, если вы создаете объект SQLiteOpenHelper, убедитесь, что вы вызываете один из методов (getWritableDatabase (), getReadableDatabase () и т. Д.), Прежде чем ваше приложение умрет.

Надеюсь, это спасет кого-то еще одну царапину! …: p

SqliteOpenHelper исходный код SqliteOpenHelper , мы можем знать, что onCreate() , onUpgrade() и onDowngrade в getWritableDatabase() или getReadableDatabase() .

 public SQLiteDatabase getWritableDatabase() { synchronized (this) { return getDatabaseLocked(true); } } public SQLiteDatabase getReadableDatabase() { synchronized (this) { return getDatabaseLocked(false); } } private SQLiteDatabase getDatabaseLocked(boolean writable) { if (mDatabase != null) { if (!mDatabase.isOpen()) { // Darn! The user closed the database by calling mDatabase.close(). mDatabase = null; } else if (!writable || !mDatabase.isReadOnly()) { // The database is already open for business. return mDatabase; } } . . . . . . final int version = db.getVersion(); if (version != mNewVersion) { if (db.isReadOnly()) { throw new SQLiteException("Can't upgrade read-only database from version " + db.getVersion() + " to " + mNewVersion + ": " + mName); } db.beginTransaction(); try { if (version == 0) { onCreate(db); } else { if (version > mNewVersion) { onDowngrade(db, version, mNewVersion); } else { onUpgrade(db, version, mNewVersion); } } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); } } onOpen(db); if (db.isReadOnly()) { Log.w(TAG, "Opened " + mName + " in read-only mode"); } mDatabase = db; return db; } finally { mIsInitializing = false; if (db != null && db != mDatabase) { db.close(); } } } 

Он фактически вызывается, когда вы вызываете getReadableDatabase или getWritableDatabase .

Глубокое погружение:

Вы передаете номер версии в конструкторе SQLiteOpenHelper который хранится в переменной mNewVersion . Вот и все. На данный момент ничего не происходит.

Каждый раз, когда вы вызываете getReadableDatabase или getWritableDatabase, он вызывается методом getDatabaseLocked . Этот метод получит существующий номер версии базы данных и сравнит его с mNewVersion .

  1. Если база данных с указанным именем не существует, она будет вызывать onCreate
  2. Если новая версия больше старой версии, она будет вызывать onUpgrade .
  3. Если новая версия ниже существующей версии, будет выбрано исключение.
  4. Если они равны, они будут продолжать работу и открывать базу данных.

Что я должен писать в onCreate и onUpgrade?

onCreate должен содержать код, который создает схему в первый раз.

Вы можете оставить onUpgrade пустым первый раз, так как он не будет вызываться в первый раз. Если вы хотите изменить структуру таблицы на более позднем этапе, этот код должен войти здесь.

SQLiteOpenHelper.java (Исходный код)

 public SQLiteDatabase getWritableDatabase() { synchronized (this) { return getDatabaseLocked(true); } } public SQLiteDatabase getReadableDatabase() { synchronized (this) { return getDatabaseLocked(false); } } private SQLiteDatabase getDatabaseLocked(boolean writable) { . . final int version = db.getVersion(); if (version != mNewVersion) { if (db.isReadOnly()) { throw new SQLiteException("Can't upgrade read-only database from version " + db.getVersion() + " to " + mNewVersion + ": " + mName); } db.beginTransaction(); try { if (version == 0) { onCreate(db); } else { if (version > mNewVersion) { onDowngrade(db, version, mNewVersion); } else { onUpgrade(db, version, mNewVersion); } } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); } } onOpen(db); }