【问题标题】:Should my room database start at version 0?我的房间数据库应该从版本 0 开始吗​​?
【发布时间】:2020-05-27 18:26:07
【问题描述】:

我意识到我的数据库迁移策略不正确并重写了它。目前它看起来像这样:

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

}

使用如下所示的辅助类:

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


}

当我删除数据库并运行应用程序时,第一次访问数据库并没有按预期运行此迁移。相反,我可以看到SQLLiteOpenHelper.java 内部的数据库版本为0,正在尝试迁移到2。由于Android helper 类的这个特定部分:

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

getDatabaseLocked 方法中,我可以看到如果它从版本 0 开始,它不会运行任何迁移,而是将版本设置为您要迁移的任何版本。

这种行为对我来说没有任何意义,所以我认为我遗漏了一些东西。我尝试了一个 hacky 解决方法,即强制迁移到 1(通过创建不同的 RoomDatabase 类)然后运行上面的工作。我也尝试过手动将数据库版本设置为 1,但这似乎也不是正确的解决方案。

如果您需要更多上下文代码,请告诉我

【问题讨论】:

    标签: java android sqlite android-room


    【解决方案1】:

    我不确定我是否解决了您的问题。对不起,如果我在下面的回答 - 事实并非如此。

    • Room 是一个使用大量注释的框架,在构建过程中会产生大量自动生成的代码。它的一部分 - 是在应用程序启动并且没有找到任何现有数据库时应该运行的 SQLite 查询。这些查询是基于实体的结构、索引、外键等形成的。
    • 假设您的数据库版本为 1,并且在构建期间生成了一些代码(代码 #1),其中包含“如果不存在则创建表...”之类的查询。
    • 之后您对表的结构进行了一些更改,将版本更改为 2。在构建期间生成了另一个代码(代码 #2),其中包含一些不同的查询(包括您对表所做的更改)。
    • 您已在设备应用程序上安装了版本 1,调用了代码 #1 - 创建了表(如果您不使用资产中的数据库预填充 - 它被创建为空)。您开始用数据填充表格,然后 - 更新到版本 2。此时,调用了 MIGRATION_1_2 块中的代码 - 以保存您的数据并使用“特殊”查询更改表格的结构。
    • 但是,如果您从设备上卸载了您的应用程序,然后安装了版本 2 的应用程序,您的代码 #2 将被调用来创建实际适用于版本 2 的表,不需要迁移,是吗?所以在这种情况下为“0”版本 - 之前安装的数据库版本,因为没有安装数据库 - 它是 0。

    我不清楚您期望什么样的迁移(在迁移中有一些插入一些值的块)。如果此迁移的唯一变化是 - 将一些预定义值插入到某个表中 - 那么也许您应该 prepopulate your initial database from assets or from file

    【讨论】:

    • 啊,那我想我误解了迁移空间的使用。我希望用它们来填充数据库表。我没有意识到我应该只将它们用于结构数据库更改(列/表等)
    猜你喜欢
    • 1970-01-01
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多