onUpgrade方法是否曾被调用?

SQLiteOpenHelperonUpgrade方法曾经被调用过吗? 如果是这样的话,什么时候叫什么? 如果不是开发者调用的,那为什么呢? 这个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()onDowngradegetWritableDatabase()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(); } } } 

调用getReadableDatabasegetWritableDatabase实际上调用它。

深潜:

在存储在名为mNewVersion的variables中的SQLiteOpenHelper的构造函数中传递版本号。 而已。 这一点什么都没有发生。

每次调用getReadableDatabase或getWritableDatabase时,都会调用一个名为getDatabaseLocked的方法。 此方法将获取数据库的现有版本号并将其与mNewVersion进行比较。

  1. 如果具有给定名称的数据库不存在,它将调用onCreate
  2. 如果新版本大于旧版本,则会调用onUpgrade
  3. 如果新版本低于现有版本,则会引发exception。
  4. 如果它们相等,它将继续并打开数据库。

我应该写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); }