表格上的房间异常:预打包的数据库具有无效的架构 [英] Room exception on table: Pre-packaged database has an invalid schema

查看:56
本文介绍了表格上的房间异常:预打包的数据库具有无效的架构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的任务是将当前应用程序的架构(使用Cupboard)迁移到Room,在第一部分工作中我遇到了一些问题,即迁移目前以Java语言编写的数据库对象(Cupboard仅支持Java),以使它们与Room一起使用.这是一个例子:

 公共类ItemDb {公共Long _id;公共字符串类型;public String子类型;公共长排定时间;public int迭代;public String data1;public String data2;public String data3; 

这是数据库中的样子:

我对这个 entity 所做的工作是在Kotlin中创建一个 @Entity 类,以供在Room中使用,它看起来像这样:

  @Entity(tableName ="ItemDb")数据类ItemDb(@PrimaryKey(autoGenerate = true)val _id:长吗?= 0,val类型:字符串,val子类型:字符串,valcheduledTime:长,val迭代:Int,val data1:字符串?= null,val data2:字符串?= null,val data3:字符串?=空) 

每当我尝试查询数据库时,都会出现此异常:

预打包的数据库具有无效的架构:ItemDb(com.example.room.model.items.ItemDb).预期的:TableInfo {name ='ItemDb',列= {scheduledTime = Column {name ='scheduledTime',type ='INTEGER',affinity ='3',notNull = true,primaryKeyPosition = 0,defaultValue ='null'},subtype =列{name ='subtype',类型='TEXT',亲和力='2',notNull = true,primaryKeyPosition = 0,defaultValue ='null'},data3 =列{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 = true,primaryKeyPosition = 0,defaultValue ='null'},_ id = Column {name ='_ id',type ='INTEGER',关联='3',notNull = false,primaryKeyPosition = 1,defaultValue ='null'},type = Column {name ='type',type ='TEXT',affinity ='2',notNull = true,primaryKeyPosition = 0,defaultValue ='null'}},foreignKeys = [],索引= []}成立:TableInfo {name ='ItemDb',列= {scheduledTime = Column {name ='scheduledTime',type ='INTEGER',affinity ='3',notNull = false,primaryKeyPosition = 0,defaultValue ='null'},subtype =列{name ='subtype',类型='TEXT',亲和力='2',notNull = false,primaryKeyPosition = 0,defaultValue ='null'},data3 =列{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',关联='3',notNull = false,primaryKeyPosition = 1,defaultValue ='null'},type = Column {name ='type',type ='TEXT',affinity ='2',notNull = false,primaryKeyPosition = 0,defaultValue ='null'}},foreignKeys = [],索引= []}

通过比较两者,我可以看到某些字段应被标记为 notNull ,但它们似乎被标记为 nullable 而不是即使Kotlin类通过避免使用可为空的?来将字段声明为 notNull .

我做错了什么?如果您需要有关数据库体系结构的更多信息,我可以轻松提供它们.谢谢!

解决方案

在错误消息中,预期"模式是Room从 ItemDb 的Kotlin声明中创建的.它将 type subType scheduledTime iteration 正确显示为非空列,所有其他列都可以为空./p>

我没有使用过Cupboard,并且假设它是通过您的 ItemDb Java声明创建数据库的.报告已预先打包的Cupboard数据库的模式的找到"模式表明,当Cupboard创建数据库时,所有列都声明为可为空(即,没有NOT NULL).

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

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

  CREATE TABLE new_ItemDb(_id INTEGER PRIMARY KEY AUTOINCREMENT,类型为INTEGER NOT NULL,子类型为INTEGER NOT NULL,调度时间为INTEGER NOT NULL,迭代INTEGER NOT NULL,data1 TEXT,data2 TEXT,data3 TEXT) 

可以在从迁移文档:

 //从2.迁移到3. 2. Roomval MIGRATION_2_3 = object:Migration(2,3){覆盖趣味迁移(数据库:SupportSQLiteDatabase){database.execSQL("创建表new_Song(id INTEGER PRIMARY KEY NOT NULL,名称TEXT,标记TEXT NOT NULL DEFAULT'')"".trimIndent())database.execSQL("INSERT INTO new_Song(ID,名称,标签)选择ID,名称,标签FROM歌曲"".trimIndent())database.execSQL("DROP TABLE Song")database.execSQL("ALTER TABLE new_Song RENAME TO Song")}} 

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

my task is to migrate the current architecture of our app (using Cupboard) to Room and I am encountering some issues on the very first piece of work, which is migrating the database objects, written in Java for now (Cupboard only supports Java), to make them work with Room. This is an example:

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;

and this is how it looks like in the database:

What I've done with this entity is creating an @Entity class in Kotlin to be used in Room and it looks like this:

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

Whenever I try to query the database I get this exception:

Pre-packaged database has an invalid schema: ItemDb(com.example.room.model.items.ItemDb). Expected: 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'}, 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=[]} Found: 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=[]}

By comparing the twos I can see that some fields are expected to be marked notNull but they seem to be marked nullable instead even though the Kotlin class is declaring the fields as notNull by avoid using the nullable ?.

What am I doing wrong? If you need more information regarding the architecture of the Database I can provide them easily. Thanks!

解决方案

In the error message, the "expected" schema is what Room created from your Kotlin declaration of ItemDb. It correctly shows type, subType, scheduledTime and iteration as non-null columns, with all others nullable.

I've not used Cupboard and am presuming it creates a database from your ItemDb Java declaration. The "found" schema, which reports the schema for the prepackaged Cupboard database, indicates that when Cupboard created the database, all columns were declared nullable (i.e. without NOT NULL).

To use the prepackaged database, you will need to perform a migration step that will create a new table with NOT NULL specified for the applicable fields. You then need to copy all the rows from the ItemDb table in the prepackaged database to the new table, with some table re-names (see example below).

The create-statement for the new table will be something like this:

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)

The migration operations can be modeled after this example copied from the documentation for migrations:

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

Before investing the time making the code changes described above, you could confirm my analysis by temporarily changing your Kotlin definition of ItemDb to make all fields nullable, then retrying your use of the prepackaged database. I would expect the import to succeed.

这篇关于表格上的房间异常:预打包的数据库具有无效的架构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆