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

99封情书 提交于 2021-02-11 17:25:28

问题


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!


回答1:


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.



来源:https://stackoverflow.com/questions/62063192/room-exception-on-table-pre-packaged-database-has-an-invalid-schema

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!