android - SQLiteOpenHelper onCreate 运行两次?

标签 android sqlite sqliteopenhelper

在我的数据库处理程序类(扩展 SQLiteOpenHelper)中,我有 onCreate() 方法:

@Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(CREATE_TABLE_TASKS); 
    db.execSQL(CREATE_TABLE_CONTACTS);
}
有时(非常罕见,但仍然)这会导致崩溃,因为显然第一个表已经存在。显然我可以(并且确实)将 IF NOT EXISTS 添加到语句中来解决此问题,但我想知道的是运行 onCreate() 的情况如果表已经存在。这通常是不应该发生的,所以我可能搞砸了一些事情,但我不知道是什么。

最佳答案

I want to know is what are the circumstances where onCreate() would be run if the table already exists

竞争条件:多个线程尝试通过 getReadableDatabase()getWritableDatabase() 获取数据库的控制权。

特别是如果线程在 code 中的 getVersion()setVersion() 之间交错。 :

242            final int version = db.getVersion();
243            if (version != mNewVersion) {
...
251                    if (version == 0) {
252                        onCreate(db);
253                    } else {
254                        if (version > mNewVersion) {
255                            onDowngrade(db, version, mNewVersion);
256                        } else {
257                            onUpgrade(db, version, mNewVersion);
258                        }
259                    }
260                    db.setVersion(mNewVersion);

涉及大量处理和一些磁盘 I/O,因此两个线程在这场竞争中结束并不困难。

可能的解决方案:

  • 同步:使用 Java 同步原语来防止其他线程同时尝试创建数据库。

  • 具有同步功能的单例。确保只有一个数据库助手。

  • 仅在单个线程中访问数据库。

关于android - SQLiteOpenHelper onCreate 运行两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26127147/

相关文章:

android - 在 android : "The method getWindowManager is undefined" 上获取窗口大小时出错

database - SQLite 仅当值不为空时更新列

java - android从数据库类内部传递变量

ruby-on-rails - rake db:create“未知的无法解析YAML” sqlite3

android - 我需要从数据库中获取数据并在另一个 Activity 中显示它们

android - 如何删除 SQLiteDatabase 中的一行 - Android Content Provider

android - 如何在android上模拟PC的Esc键

java - 如何将位图从服务发送到 java、android 中的主程序?

android - react-native run-android 后的两个app

sqlite - JPA EntityManager不在SQLite数据库中提交更改