表上的房间异常。预先打包的数据库有一个无效的模式。

问题描述 投票:0回答:1

我的任务是将我们应用的当前架构(使用Cupboard)迁移到Room上,我在第一项工作中遇到了一些问题,那就是迁移数据库对象,目前是用Java编写的(Cupboard只支持Java),使它们能与Room一起工作。这是一个例子。

public class ItemDb {

public Long _id;
public String type;
public String subtype;
public long scheduledTime;
public int iteration;
public String data1;
public String data2;
public String data3;

这是数据库中的样子:

enter image description here

我用这个做了什么 实体 正在创建一个 @Entity 在Kotlin中的类中,要在Room中使用,它看起来像这样。

@Entity(tableName = "ItemDb")
data class ItemDb(
        @PrimaryKey(autoGenerate = true)
        val _id: Long? = 0,
        val type: String,
        val subtype: String,
        val scheduledTime: Long,
        val iteration: Int,
        val data1: String? = null,
        val data2: String? = null,
        val data3: String? = null
)

每当我试图查询数据库时,我都会收到这样的异常:

预包装的数据库有一个无效的模式。ItemDb(com.example.room.model.items.ItemDb)。 预期的。 TableInfo{name='ItemDb', columns={scheduledTime=Column{name='scheduleTime', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, subtype=Column{name='subtype', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, data3=Column{name='data3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, data2=Column{name='data2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, data1=Column{name='data1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, iteration=Column{name='iteration', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}。_id=Column{name='_id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, type=Column{name='type', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}。 找到了。 TableInfo{name='ItemDb', columns={scheduledTime=Column{name='scheduledTime', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, subtype=Column{name='subtype', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0。defaultValue='null'}, data3=Column{name='data3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, data2=Column{name='data2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, data1=Column{name='data1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, iteration=Column{name='iteration', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}。_id=Column{name='_id', type='integer', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, type=Column{name='type', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}。

通过对比二者,我可以看到,有些字段预计会被标记为 notNull 但它们似乎被标记为 nullable 而是 纵然 Kotlin类将字段声明为 notNull 通过避免使用可空的 ?.

我做错了什么?如果你需要更多关于数据库架构的信息,我可以很容易地提供它们。谢谢!我的任务是将我们应用的当前架构(使用Cupboard)迁移到Room,我遇到了一些问题。

android sqlite android-room android-database
1个回答
1
投票

在错误信息中,"预期的 "模式是Room从你的Kotlin声明中创建的。ItemDb. 它正确地显示 type, subType, scheduledTimeiteration 作为非空列,其他的都可以为空。

我没有使用过Cupboard,我猜测它是根据你的数据创建一个数据库。ItemDb Java声明。 "发现 "模式,它报告了预包装Cupboard数据库的模式,表明当Cupboard创建数据库时,所有列都被声明为nullable(即没有NOT NULL)。

要使用预包装的数据库,您将需要 办理迁移手续 将会创建一个新的表格,其中包含 NOT NULL 指定适用字段的名称。然后,您需要将预包装数据库中ItemDb表的所有行复制到新表中,并重新命名一些表(见下面的例子)。

新表的create-statement将是这样的。

CREATE TABLE new_ItemDb (_id INTEGER PRIMARY KEY AUTOINCREMENT,
    type INTEGER NOT NULL, subType INTEGER NOT NULL, scheduledTime INTEGER NOT NULL,
    iteration INTEGER NOT NULL, data1 TEXT, data2 TEXT, data3 TEXT)

迁移操作可以仿照这个例子,复制自... ... 迁移文件:

// Migration from 2 to 3, Room 2.2.0
val MIGRATION_2_3 = object : Migration(2, 3) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("""
                CREATE TABLE new_Song (
                    id INTEGER PRIMARY KEY NOT NULL,
                    name TEXT,
                    tag TEXT NOT NULL DEFAULT ''
                )
                """.trimIndent())
        database.execSQL("""
                INSERT INTO new_Song (id, name, tag)
                SELECT id, name, tag FROM Song
                """.trimIndent())
        database.execSQL("DROP TABLE Song")
        database.execSQL("ALTER TABLE new_Song RENAME TO Song")
    }
}

在投入时间进行上述代码修改之前,你可以通过临时改变Kotlin对以下内容的定义来确认我的分析。ItemDb 使所有字段为空,然后重新尝试使用预包装的数据库。 我希望导入能成功。

© www.soinside.com 2019 - 2024. All rights reserved.