onUpgrade方法是否曾被调用?
SQLiteOpenHelper
的onUpgrade
方法曾经被调用过吗? 如果是这样的话,什么时候叫什么? 如果不是开发者调用的,那为什么呢? 这个function真的发生了什么? 我已经看到了所有表格的例子,但是一个评论说,放弃所有的表格不是你应该做的。 有什么build议么?
当你使用比打开的数据库版本更新的版本构造SQLiteOpenHelper时会调用它。 要做什么取决于旧版本和新版本之间的数据库更改。 唯一的情况是,当您不删除更改的表格时,更改的内容多于添加的列。 然后,您可以使用ALTER TABLE语句将新列添加到表签名。
对于那些想知道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); }
如果您正在使用SQLiteOpenHelper,则每次更改数据库版本时都会调用onUpgrade。 还有一个额外的要求,这个工作。 数据库名称必须保持不变。
Old Version: dbName = "mydb.db" dbVersion = 1 New Version: dbName = "mydb.db" dbVersion = 2
在内容提供者的onCreate中,创build一个带有这些参数的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 } }
回顾所有的post和运行debugging代码,当我看到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调用。 我没有检查其他方法,因为这些方法符合我的需要。
继续阅读,踢球者来了…
当我最终意识到在我的debugging过程中db版本正在更新时,我最初的Activity中的这个代码给了我启发… 呃!
DatabaseHelper dbHelper = new DatabaseHelper( this ); dbHelper.checkDatabaseVersion();
注意:调用DatabaseHelper构造函数更新数据库版本
在构造函数调用之后,数据库被标记为新版本。 在调用getWritableDatabase()或getReadableDatabase()之前杀死应用程序,而您正在使用新版本。 此后,新的执行从不调用onUpgrade方法,直到DATABASE_VERSION再次增加。 ( 叹气!现在看起来很荒唐 🙂
我的build议是添加某种“checkDatabaseVersion()”到你的应用程序的早期阶段。 或者,如果您创build了一个SQLiteOpenHelper对象,请确保在应用程序死亡之前调用其中一个方法(getWritableDatabase(),getReadableDatabase()等)。
我希望这可以拯救别人一样的头抓!!:第
纵观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
时实际上调用它。
深潜:
在存储在名为mNewVersion
的variables中的SQLiteOpenHelper
的构造函数中传递版本号。 而已。 这一点什么都没有发生。
每次调用getReadableDatabase或getWritableDatabase时,都会调用一个名为getDatabaseLocked
的方法。 此方法将获取数据库的现有版本号并将其与mNewVersion
进行比较。
- 如果具有给定名称的数据库不存在,它将调用
onCreate
- 如果新版本大于旧版本,则会调用
onUpgrade
。 - 如果新版本低于现有版本,则会引发exception。
- 如果它们相等,它将继续并打开数据库。
我应该写onCreate和onUpgrade?
onCreate
应该包含第一次创build模式的代码。
您可以在第一次空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); }