我的任务是将我们应用的当前架构(使用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;
这是数据库中的样子:
我用这个做了什么 实体 正在创建一个 @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,我遇到了一些问题。
在错误信息中,"预期的 "模式是Room从你的Kotlin声明中创建的。ItemDb
. 它正确地显示 type
, subType
, scheduledTime
和 iteration
作为非空列,其他的都可以为空。
我没有使用过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
使所有字段为空,然后重新尝试使用预包装的数据库。 我希望导入能成功。