问题
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