Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

Ответ 2

Для тех из вас, кто хотел бы узнать точный момент, когда вызов 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);
}

Ответ 3

если вы используете 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
        }

}

Ответ 4

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

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

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

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

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

Надеюсь, это сэкономит кому-то еще тугую голову!...: p

Ответ 5

Изучая исходный код 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();
        }
    }
}

Ответ 6

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

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

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

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

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

Что я должен писать в 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);
 }