【问题标题】:SQLiteOpenHelper doesn't update database while changing the DB versionSQLiteOpenHelper 在更改数据库版本时不更新数据库
【发布时间】:2017-10-19 21:42:49
【问题描述】:

我有一个关于 SQLiteOpenHelper 的问题。 我创建了一个单例来访问数据库。在构造函数中,我使用 DATABASE_VERSION 调用(SQLiteOpenHelper 的)超级方法,所以如果我增加 DATABASE_VERSION 应该调用 onUpgrade 对吗? 但是永远不会调用 onUpgrade 。 是否有其他属性要更改以升级数据库或其他什么?

已经谢谢了!

代码示例:

private static final int DATABASE_VERSION = 101;
private static final String DATABASE_NAME = "dbName.db";

private static final String SQL_CREATE_TESTDB_TABLE = "CREATE TABLE TESTTABLE (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)";
private static final String SQL_DELETE_TESTDB_TABLE = "DROP TABLE IF EXISTS TESTTABLE";    


//Singleton
private static TestDatabase testDatabase = null;

public static TestDatabase getTestDatabase(Context context){
    if(testDatabase == null){
        testDatabase = new TestDatabase(context);
    }
    return testDatabase;
}

//Constructor
private TestDatabase(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);

    this.getWritableDatabase(); //DB should upgrade?
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL(SQL_DELETE_TESTDB_TABLE);
    this.onCreate(db);
}

@Override
public void onCreate(SQLiteDatabase db) {
    //create table
    db.execSQL(SQL_CREATE_TESTDB_TABLE);
}

//主要活动代码部分:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    TestDatabase.getTestDatabase(this.getApplicationContext());

【问题讨论】:

  • PUT 你的 onUpgrade 方法
  • @Xenolion 我都添加了
  • 您能提供SQL_DELETE_TESTDB_TABLESQL_DELETE_TESTDB_TABLE 解决的问题吗?可能是由于他们的价值观。
  • @MikeT 都已添加
  • 尝试运行我自己的带有日志记录的版本可以说构造函数正在被调用,但随后不会继续 onCreate。现在逐步调试,看看我是否能找出发生了什么。

标签: android sql database sqlite sqliteopenhelper


【解决方案1】:

在您的 TestDatabase 类(扩展 SQLiteOpenHelper 的类)上,您需要重写 onUpgrade 方法。我相信你已经有了 onCreate 方法。示例将是,

  public TestDatabase (Context context) {
    super(context,DATABASE_NAME, null, DATABASE_VERSION);
}

 @Override
public void onCreate(SQLiteDatabase db) {
    db.execSQL(<YOUR QUERIES TO EXECUTE WHEN APPLICATION IS FIRST INSTALLED>);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL(<YOUR QUERY WHEN DB VERSION CHANGES>);

}

【讨论】:

  • 添加了两个函数,设置断点时它们不会被触发。
  • OnCreate 仅在您的应用首次安装时被调用。如果您使用的是android studio和模拟器​​,它不会卸载您的应用程序,所以它就像更新一样。对于 onUpgrade 到 tirgger,您需要更新(增加)您的 DATABASE_VERSION 。还要添加您的 TestDatabase 的构造函数,如答案中更新的那样。
  • 构造函数在代码示例中。如果我增加 DATABASE_VERSION DATABASE_VERSION onUpgrade 将不会被触发。
  • 我正在真实设备上开发,通过卸载应用程序(adb 卸载 ...)并通过 Android Studio 重新安装应用程序,onCreate 也不会被触发。
  • 你能把构造函数公开吗?
【解决方案2】:

数据库名称常量通常不包含“.db”扩展名,但如果这是导致您的错误,我会感到惊讶。

getWriteableDatabase() 调用应该足以触发 onCreate() 或 onUpgrade(),但也许它正在被编译器优化,因为它的结果未被使用?

我将尽快测试这两个选项并编辑结果。

编辑:当我测试时,这些都没有引起问题,你确定在某处调用 getTestDatabase 吗?如果没有,那么实际上并没有创建实例,这可以解释为什么代码没有运行。

【讨论】:

  • 我已经从 MainActivity 添加了 onCreate 函数。
【解决方案3】:

根据我的 cmets。我确定我遇到了同样的问题,但我随后在this.getWriteableDatabase(); 添加了一个断点并进行了调试。然后,我尝试在

处进入代码(提出警告,但仍然Sources for Android API 26 Platform not found
public SQLiteDatabase getWritableDatabase() {
    throw new RuntimeException("Stub!");
}

但此后一直有效。因此,我建议尝试做同样的事情(也许尝试清理并重建)。

我的代码(如下)与发布的代码非常相似,但我编写了表创建代码并添加了一些日志记录。记录的结果非常确认如下:-

10-20 21:12:48.879 24448-24448/? D/TESTDB: getTestDatabase invoked
10-20 21:12:48.879 24448-24448/? D/TESTDB: Calling Constructor from singleton
10-20 21:12:48.879 24448-24448/? D/TESTDB: Constructor Invoked
10-20 21:18:30.177 29719-29719/? D/TESTDB: getTestDatabase invoked
10-20 21:18:30.177 29719-29719/? D/TESTDB: Calling Constructor from singleton
10-20 21:18:30.177 29719-29719/? D/TESTDB: Constructor Invoked
10-20 21:18:44.181 29792-29792/? D/TESTDB: getTestDatabase invoked
10-20 21:18:44.181 29792-29792/? D/TESTDB: Calling Constructor from singleton
10-20 21:18:44.181 29792-29792/? D/TESTDB: Constructor Invoked

注意从这里开始,相同的代码开始工作并调用 onCreate????

10-20 21:21:29.644 31659-31659/? D/TESTDB: getTestDatabase invoked
10-20 21:21:29.644 31659-31659/? D/TESTDB: Calling Constructor from singleton
10-20 21:21:29.644 31659-31659/? D/TESTDB: Constructor Invoked
10-20 21:21:29.666 31659-31659/? D/TESTDB: Oncreate Invoked
10-20 21:25:38.967 1069-1069/? D/TESTDB: getTestDatabase invoked
10-20 21:25:38.967 1069-1069/? D/TESTDB: Calling Constructor from singleton
10-20 21:25:38.967 1069-1069/? D/TESTDB: Constructor Invoked
10-20 21:26:06.221 1069-1069/? D/TESTDB: Oncreate Invoked
10-20 21:28:38.297 3941-3941/? D/TESTDB: getTestDatabase invoked
10-20 21:28:38.297 3941-3941/? D/TESTDB: Calling Constructor from singleton
10-20 21:28:38.297 3941-3941/? D/TESTDB: Constructor Invoked
10-20 21:28:44.602 4040-4040/? D/TESTDB: getTestDatabase invoked
10-20 21:28:44.602 4040-4040/? D/TESTDB: Calling Constructor from singleton
10-20 21:28:44.602 4040-4040/? D/TESTDB: Constructor Invoked
10-20 21:34:39.608 9786-9786/? D/TESTDB: getTestDatabase invoked
10-20 21:34:39.608 9786-9786/? D/TESTDB: Calling Constructor from singleton
10-20 21:34:39.608 9786-9786/? D/TESTDB: Constructor Invoked
10-20 21:36:48.139 10495-10495/? D/TESTDB: getTestDatabase invoked
10-20 21:36:48.139 10495-10495/? D/TESTDB: Calling Constructor from singleton
10-20 21:36:48.139 10495-10495/? D/TESTDB: Constructor Invoked
10-20 21:36:48.188 10495-10495/? D/TESTDB: Oncreate Invoked

注意!我没有删除上述多次运行的数据库(我最后一次运行)。

在调用 onUpgrade 时将版本更改为 102

10-20 21:41:49.007 15098-15098/? D/TESTDB: getTestDatabase invoked
10-20 21:41:49.007 15098-15098/? D/TESTDB: Calling Constructor from singleton
10-20 21:41:49.007 15098-15098/? D/TESTDB: Constructor Invoked
10-20 21:41:49.011 15098-15098/? D/TESTDB: onUpgrade invoked

我使用的代码(请原谅明目张胆的抄袭 :))哦,现在的版本是 102(最初使用的是 101):-

public class TestDatabase extends SQLiteOpenHelper {

    private static final int DATABASE_VERSION = 102;
    private static final String DATABASE_NAME = "dbName.db";

    //Singleton
    private static TestDatabase testDatabase = null;

    public static TestDatabase getTestDatabase(Context context) {
        Log.d("TESTDB","getTestDatabase invoked");
        if (testDatabase == null) {
            Log.d("TESTDB", "Calling Constructor from singleton");
            testDatabase = new TestDatabase(context);
        }
        return testDatabase;
    }

    private TestDatabase(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        Log.d("TESTDB","Constructor Invoked");
        this.getWritableDatabase();
    }


    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d("TESTDB","Oncreate Invoked");
        String tblcrt = "CREATE TABLE IF NOT EXISTS testtable (" +
                "_id INTEGER PRIMARY KEY," +
                "COL1 TEXT" +
                ")";
        db.execSQL(tblcrt);

    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        Log.d("TESTDB","onUpgrade invoked");
    }
}

还有:-

......
TestDatabase testdb;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    setViewIDs();
    setDBViewerButton(mButton1); // setup Button 1 for DBViewer

    testdb = TestDatabase.getTestDatabase(this);
    .....
}

【讨论】:

  • 我已经测试了代码,并且发生了一件非常奇怪的事情。在模拟器上运行我的代码时,会触发 onCreate 和 onUpdate。在真实设备上运行代码时,不会触发 onCreate 和 onUpdate。
  • @GilianJoosen 尝试将public static TestDatabase getTestDatabase(..... 更改为static synchronized TestDatabase getTestDatabase(.....
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多