簡體   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