[英]Is the onUpgrade method ever called?
是否曾调用SQLiteOpenHelper
的onUpgrade
方法? 如果是这样,什么时候被召唤? 如果它没有被开发人员调用,那为什么呢? 这个功能到底发生了什么? 我已经看到了删除所有表的示例,但随后评论说放弃所有表并不是你应该做的。 有什么建议?
对于那些想知道调用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中,您创建了一个采用这些参数的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
}
}
当您构造一个版本比打开的数据库版本更新的SQLiteOpenHelper时,会调用它。 做什么取决于旧版本和新版本之间的数据库更改。 如果不删除已更改的表,则唯一的情况是更改的位置超过添加的列。 然后,您可以使用ALTER TABLE语句将新列添加到表签名。
回顾所有帖子并运行调试代码,当我看到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版本正在更新时,我的初始Activity中的代码启发了我... 唉!
DatabaseHelper dbHelper = new DatabaseHelper( this );
dbHelper.checkDatabaseVersion();
注意:调用DatabaseHelper构造函数会更新db版本
在构造函数调用之后,db被标记为新版本。 在调用getWritableDatabase()或getReadableDatabase()之前杀死应用程序并且您使用的是新版本。 此后,新的执行永远不会调用onUpgrade方法,直到再次增加DATABASE_VERSION。 ( 感叹!现在看起来很荒谬 :)
我的建议是在应用程序的早期阶段添加某种“checkDatabaseVersion()”。 或者,如果您创建一个SQLiteOpenHelper对象,请确保在应用程序死亡之前调用其中一个方法(getWritableDatabase(),getReadableDatabase()等)。
我希望这可以节省别人同样的头脑刮伤!...:p
查看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
进行比较。
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.