Java 是否调用过 onUpgrade 方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3163845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is the onUpgrade method ever called?
提问by Mohit Deshpande
Is the onUpgrade
method of SQLiteOpenHelper
ever called? If so, when is it called and by what? If it is not called by the developers, then why is it there? What really happens with that function? I have seen examples where it drops all the tables, but then a comment says that dropping all the tables is not what you should do. Any suggestions?
曾经调用过的onUpgrade
方法SQLiteOpenHelper
吗?如果是这样,它是什么时候调用的,用什么调用的?如果开发者没有调用它,那它为什么会在那里呢?这个函数到底发生了什么?我看过它删除所有表的例子,但随后有评论说删除所有表不是你应该做的。有什么建议?
采纳答案by ognian
It is called when you construct a SQLiteOpenHelper with version newer than the version of the opened database. What to do depends on the changes in the database that are made between the old and new versions. The only case when you don't drop a changed table is when the change is noting more than an added column. Then you can use ALTER TABLE statement to add the new column to the table signature.
当您构造版本比打开的数据库版本更新的 SQLiteOpenHelper 时,它会被调用。要做什么取决于在旧版本和新版本之间所做的数据库更改。不删除已更改的表的唯一情况是更改不仅仅是添加的列。然后您可以使用 ALTER TABLE 语句将新列添加到表签名中。
回答by dev.serghini
if your are using the SQLiteOpenHelper the onUpgrade will be called whenever you change the DB version. There is an additional requirement for this to work. The db name has to remain the same.
如果您使用的是 SQLiteOpenHelper,则每当您更改数据库版本时都会调用 onUpgrade。要使其正常工作,还有一个额外的要求。数据库名称必须保持不变。
Old Version:
dbName = "mydb.db"
dbVersion = 1
New Version:
dbName = "mydb.db"
dbVersion = 2
in the onCreate of the content provider you create an instance of the SQLiteOpenHelper that takes these params. Your SQLiteOpenHelper implementation would look like this:
在内容提供程序的 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
}
}
回答by lazyList
For those of you who would like to know the exact moment when onUpgrade()
gets called, it is during a call to either getReadableDatabase()
or getWriteableDatabase()
.
对于那些想知道onUpgrade()
被调用的确切时间的人,是在调用getReadableDatabase()
或 的过程中getWriteableDatabase()
。
To those who are not clear how it ensure it gets triggered, the answer is: It is triggered when the database version provided to the constructor of SqLiteOpenHelper
is updated. Here is a example
对于那些不清楚它如何确保触发的人来说,答案是:当提供给构造函数的数据库版本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
}
now to...onUpgrade()
现在到...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);
}
回答by RobinM
Reviewing all of the posts and running debug code it still was not clear to me when I would see onUpgrade getting called. I was starting to think that Android had a serious flaw..
查看所有帖子并运行调试代码,当我看到 onUpgrade 被调用时,我仍然不清楚。我开始认为 Android 有一个严重的缺陷..
The info on this page led me to my final resolution. Thanks a bunch to all contributors!
此页面上的信息引导我做出最终决定。非常感谢所有贡献者!
This solved it for me...
这为我解决了它...
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...
}
It's true that getWritableDatabase() and getReadableDatabase() does result in the onUpgrade call. I didn't check other methods since these fit the bill for my needs.
getWritableDatabase() 和 getReadableDatabase() 确实会导致 onUpgrade 调用。我没有检查其他方法,因为这些方法符合我的需要。
Keep reading, the kicker is coming...
继续阅读,踢球者来了……
This code in my initial Activity enlightened me when I finally realized that the db version was updating during my debugging... ugh!
当我终于意识到 db 版本在我的调试过程中正在更新时,我最初 Activity 中的这段代码启发了我…… 呃!
DatabaseHelper dbHelper = new DatabaseHelper( this );
dbHelper.checkDatabaseVersion();
NOTE: calling the DatabaseHelper constructor updates the db version
注意:调用 DatabaseHelper 构造函数会更新数据库版本
After the constructor call, the db was tagged with the new version. Kill the app before a call to getWritableDatabase() or getReadableDatabase() and you're on the new version. Thereafter new executions never call the onUpgrade method until DATABASE_VERSION is increased again. (sigh! now it seems ridiculously obvious:)
在构造函数调用之后,数据库被标记为新版本。在调用 getWritableDatabase() 或 getReadableDatabase() 之前终止应用程序,您将使用新版本。此后新的执行永远不会调用 onUpgrade 方法,直到 DATABASE_VERSION 再次增加。(叹气!现在看起来很明显:)
My suggestion is to add some sort of "checkDatabaseVersion()" to the early stages of your app. Alternately, if you create a SQLiteOpenHelper object make sure you call one of the methods (getWritableDatabase(), getReadableDatabase(), etc.) before your app dies..
我的建议是在应用程序的早期阶段添加某种“checkDatabaseVersion()”。或者,如果您创建 SQLiteOpenHelper 对象,请确保在应用程序终止之前调用其中一种方法(getWritableDatabase()、getReadableDatabase() 等)。
I hope this saves someone else the same head scratching!... :p
我希望这可以让其他人免于同样的头疼!...:p
回答by Folyd
Looking into the SqliteOpenHelper
source code, we can know onCreate()
,onUpgrade()
and onDowngrade
get called in getWritableDatabase()
or getReadableDatabase()
method.
查看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();
}
}
}
回答by Siva Prakash
It is actually calledwhen you call getReadableDatabase
or getWritableDatabase
.
它实际上是在您调用getReadableDatabase
or时调用的getWritableDatabase
。
Deep dive:
深潜:
You pass version number in the constructor of SQLiteOpenHelper
which is stored in a variable called mNewVersion
. That's it. Nothing happens at this point.
您在构造函数中传递版本号,该版本号SQLiteOpenHelper
存储在一个名为mNewVersion
. 就是这样。此时没有任何反应。
Everytime you call getReadableDatabase or getWritableDatabase, it will call a method called getDatabaseLocked
. This method will get the existing version number of the database and compare it with the mNewVersion
.
每次调用 getReadableDatabase 或 getWritableDatabase 时,它都会调用一个名为 的方法getDatabaseLocked
。此方法将获取数据库的现有版本号并将其与mNewVersion
.
- If the database with the given name doesn't exist it will call
onCreate
- If the new version is greater than old version it will call
onUpgrade
. - If the new version is lower than existing version, an exception will be thrown.
- If they are equal it will go ahead and open the database.
- 如果具有给定名称的数据库不存在,它将调用
onCreate
- 如果新版本大于旧版本,它将调用
onUpgrade
. - 如果新版本低于现有版本,则会抛出异常。
- 如果它们相等,它将继续打开数据库。
What should I write in onCreate and onUpgrade ?
我应该在 onCreate 和 onUpgrade 中写什么?
onCreate
should contain the code that creates a schema for the first time.
onCreate
应该包含第一次创建架构的代码。
You can leave onUpgrade
empty first time since it won't be called the first time. When you want to change the table structure at later stage, that code should go in here.
您可以onUpgrade
第一次留空,因为它不会第一次被调用。当您想在稍后阶段更改表结构时,该代码应该放在此处。
SQLiteOpenHelper.java(Source code)
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);
}