[英]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
。 它正确地将type
、 subType
、 scheduledTime
和iteration
显示为非空列,所有其他列都可以为空。
我没有使用过 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.