简体   繁体   English

我的房间数据库应该从版本 0 开始吗?

[英]Should my room database start at version 0?

I have realised that my database migration strategy was incorrect and have rewritten it.我意识到我的数据库迁移策略不正确并重写了它。 At the moment it looks like this:目前它看起来像这样:

@Database(entities = {SaveData.class, Achievement.class}, version = 2, exportSchema = false)
@TypeConverters(MapConverters.class)
public abstract class AppDatabase extends RoomDatabase {

    public abstract SaveDataDAO saveDataDAO();

    public abstract AchievementDAO achievementDAO();

}

With a helper class that looks like this:使用如下所示的助手 class:

public class AppDatabaseHelper {

    private static AppDatabase db;

    private AppDatabaseHelper() {
        // static utility
    }

    private static final Migration MIGRATION_1_2 =
            new Migration(1, 2) {
                @Override
                public void migrate(@NonNull SupportSQLiteDatabase database) {
                    Set<AchievementType> achievementTypes = EnumSet.allOf(AchievementType.class);
                    String values = achievementTypes.stream().map(AppDatabaseHelper::createRow).collect(Collectors.joining(", "));
                    String fullQuery = "INSERT OR IGNORE INTO Achievement(name, current, total) VALUES " + values;
                    database.execSQL(fullQuery);
                }
            };

    private static String createRow(AchievementType achievementType) {
        String name = achievementType.name();
        int total = achievementType.getTotal();
        return String.format("('%s',0,%s)", name, total);
    }

    public static AppDatabase getDatabase(Context context) {
        if (db == null) {
            db = Room.databaseBuilder(context.getApplicationContext(),
                    AppDatabase.class, "game")
                    .addMigrations(MIGRATION_1_2)
                    .build();
        }
        return db;
    }


}

When I delete the database and run the app, accessing the database for the first time does not run this migration as expected.当我删除数据库并运行应用程序时,第一次访问数据库不会按预期运行此迁移。 Instead, I can see that the version of the database inside SQLLiteOpenHelper.java is 0, attempting to migrate to 2. Because of this specific part of the Android helper class:相反,我可以看到SQLLiteOpenHelper.java中的数据库版本为 0,试图迁移到 2。由于 Android 助手 ZA2F2ED4F8EBC2CBB4C21A29DC4 的这个特定部分:

                    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();
                    }

inside the getDatabaseLocked method, I can see that it will not run any migrations if it starts at version 0, and will instead just set the version to be whatever you are migrating up to.getDatabaseLocked方法中,我可以看到如果它从版本 0 开始,它将不会运行任何迁移,而是将版本设置为您要迁移的任何版本。

This behaviour doesn't make any sense to me, so I assume I am missing something.这种行为对我来说没有任何意义,所以我认为我遗漏了一些东西。 I have tried a hacky workaround of just forcing the migration to go to 1 (by creating a different RoomDatabase class) then running the above which works.我尝试了一个 hacky 解决方法,即强制迁移到 go 到 1(通过创建不同的RoomDatabase类)然后运行上面的工作。 I have also tried manually setting the database version to be 1, but this doesn't seem to be the right solution either.我也尝试过手动将数据库版本设置为 1,但这似乎也不是正确的解决方案。

Let me know if you need more code for context如果您需要更多上下文代码,请告诉我

I am not sure I've got right your trouble.我不确定我是否解决了你的问题。 Sorry if my answer below - it's not the case.对不起,如果我在下面回答 - 事实并非如此。

  • Room is a framework that uses a lots of annotations and during build process produces a lot of autogenerated code. Room 是一个使用大量注释的框架,在构建过程中会产生大量自动生成的代码。 Part of it - is the queries for SQLite that should be run when application starts and doesn't find any existing database.其中一部分是对 SQLite 的查询,应该在应用程序启动并且找不到任何现有数据库时运行。 These queries are formed based on entities' structure, indices, foreign keys and so on.这些查询是基于实体的结构、索引、外键等形成的。
  • Let's say you had database version 1 and during build was generated some code (code #1) with the queries like "CREATE TABLE IF NOT EXIST...".假设您拥有数据库版本 1,并且在构建期间生成了一些代码(代码 #1),其中包含“如果不存在则创建表 ...”之类的查询。
  • After that you made some changes to tables' structure, changed version to 2. During build was generated another code (code #2) with the little bit different queries (including changes you've made to tables).之后,您对表的结构进行了一些更改,将版本更改为 2。在构建期间生成了另一个代码(代码 #2),其中包含一些不同的查询(包括您对表所做的更改)。
  • You've installed on device app with version 1, code #1 was invoked - tables were created (if you don't use prepopulation of database from assets - it was created empty).您已在版本 1 的设备应用程序上安装,调用了代码 #1 - 创建了表(如果您不使用资产中的数据库预填充 - 它被创建为空)。 You begin to fill tables with data and then - updated to version 2. At that, code from your MIGRATION_1_2 block was invoked - in order to save your data and just to change tables' structure with "special" query.您开始用数据填充表,然后 - 更新到版本 2。此时,调用了 MIGRATION_1_2 块中的代码 - 以保存您的数据并只是使用“特殊”查询更改表的结构。
  • But if you uninstalled your app from device and then installed app with version 2, your code #2 would be invoked to create tables actual for version 2, there is no need for migration, is it?但是,如果您从设备上卸载了您的应用程序,然后安装了版本 2 的应用程序,您的代码 #2 将被调用来创建版本 2 的实际表,不需要迁移,是吗? So "0" version in this case - version of database installed before, since there was no database installed - it is 0.所以在这种情况下是“0”版本 - 之前安装的数据库版本,因为没有安装数据库 - 它是 0。

It's not clear for me what kind of migration you expect (in Migration there is some block with insert some values).我不清楚您期望什么样的迁移(在迁移中有一些插入一些值的块)。 If the only change in this migration is -inserting some predefining values into some table - then maybe you should prepopulate your initial database from assets or from file ?如果此迁移中的唯一更改是 - 将一些预定义值插入到某个表中 - 那么也许您应该从资产或文件中预填充初始数据库

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么 Room 在迁移后删除我的数据库 - Why Room remove my database after migration 如何预填充 Room 数据库? - How do I prepopulate my Room database? Android Room:获取当前数据库版本/检查是否过时 - Android Room: Get present database version / check if is out-dated IllegalArgumentException:版本必须 &gt;= 1,为 0。在带有 Room 数据库的 Androis Studio 中 - IllegalArgumentException: Version must be >= 1, was 0. in Androis Studio with Room database 我应该如何开始分析/优化我的Java应用程序/ oracle数据库? - How should I start profiling/optimizing my java application/oracle database? 我需要使用存储在房间数据库中的按日期(开始日期和结束日期之间)的 recyclerView 过滤列表视图 - I need to filter the listview using recyclerView by date(between start date and end date) stored in Room Database 我应该在 WorkManager.getInstance().enqueue() 上传递什么上下文? (使用 MVVM + 房间数据库 + WorkManager) - What Context should i pass on WorkManager.getInstance().enqueue() ? (Using MVVM + Room Database + WorkManager) 将数据存储到 Room 数据库 - Storing data to Room database 会议室数据库更新问题 - Room Database update issue 会议室数据库观察员 - Room database observer
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM