繁体   English   中英

桌子上的房间异常:预打包的数据库具有无效的架构

[英]Room exception on table: Pre-packaged database has an invalid schema

我的任务是将我们应用程序的当前架构(使用 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;

这就是它在数据库中的样子:

在此处输入图像描述

我对这个实体所做的是在 Kotlin 中创建一个@Entity class 以在 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='scheduledTime',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'},迭代=列{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'} , 迭代=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=[], ind 冰=[]}

通过比较两者,我可以看到一些字段预计将被标记为notNull但它们似乎被标记为可为nullable即使Kotlin notNull通过避免使用可为空的? .

我究竟做错了什么? 如果您需要有关数据库架构的更多信息,我可以轻松地提供它们。 谢谢!

在错误消息中,“预期”架构是 Room 从您的 Kotlin 声明中创建的ItemDb 它正确地将typesubTypescheduledTimeiteration显示为非空列,所有其他列都可以为空。

我没有使用过 Cupboard,并且假设它会根据您的ItemDb Java 声明创建一个数据库。 “找到”模式报告预打包的 Cupboard 数据库的模式,表明当 Cupboard 创建数据库时,所有列都被声明为可为空(即没有 NOT NULL)。

要使用预打包的数据库,您需要执行迁移步骤,该步骤将创建一个新表,其中为适用字段指定了NOT NULL 然后,您需要将预打包数据库中 ItemDb 表中的所有行复制到新表中,并重新命名一些表(参见下面的示例)。

新表的创建语句将如下所示:

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")
    }
}

在花时间进行上述代码更改之前,您可以通过临时更改 ItemDb 的ItemDb定义以使所有字段可为空来确认我的分析,然后重试使用预打包的数据库。 我希望导入成功。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM