Вызывается ли метод onUpgrade? - PullRequest
33 голосов
/ 02 июля 2010

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

Ответы [ 6 ]

36 голосов
/ 24 декабря 2011

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

Для тех, кто не совсем уверен, как он запускается, ответ таков: он запускается при обновлении версии базы данных, предоставленной конструктору 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);
}
28 голосов
/ 13 апреля 2011

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

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
        }

}
21 голосов
/ 02 июля 2010

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

4 голосов
/ 30 мая 2015

Просматривая все посты и выполняя отладочный код, мне все еще не было ясно, когда я увижу, как вызывается 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. Я не проверял другие методы, так как они соответствуют моим потребностям.

Продолжайте читать, приближается кикер ...

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

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

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

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

Я предлагаю добавить своего рода "checkDatabaseVersion ()" на ранних стадиях вашего приложения. Кроме того, если вы создаете объект SQLiteOpenHelper, убедитесь, что вы вызываете один из методов (getWritableDatabase (), getReadableDatabase () и т. Д.) До того, как ваше приложение умрет.

Надеюсь, это спасет кого-то еще от того же царапин на голове! ...: p

2 голосов
/ 20 октября 2015

Рассматривая исходный код 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();
        }
    }
}
1 голос
/ 21 июня 2017

Это на самом деле называется , когда вы звоните 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);
 }
...