Android 房间给出错误 "Pre-packaged database has an invalid schema" 但导出的架构是正确的
Android Room giving error "Pre-packaged database has an invalid schema" but exported schema is correct
我正在从 SQlite 迁移到现有应用程序中的房间。因此我创建了迁移策略来创建新的临时表,将现有数据复制到临时表中并删除旧表并重命名新表。
迁移后,我检查了导出的架构,它与预期的架构完全相同,但我仍然收到“发现旧架构并收到以下错误消息”的错误。模式错误的主要区别是“类型”和#notNull“,但我已经在迁移过程中更正了它们
Pre-packaged database has an invalid schema:
User(com.afl.waterReminderDrinkAlarmMonitor.model.User)
我的用户实体
@Entity(tableName = "User" )
data class User(
@PrimaryKey
var id: Int = 0,
var age: Int = 0,
var weight: Int = 0,
var gender: String = "",
var metric: String = "",
var water: Int = 0
)
应用数据库
abstract class AppDatabase : RoomDatabase() {
abstract fun dao(): Dao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
val migration_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
//COPY USER TABLE
// Create new table
database.execSQL("CREATE TABLE IF NOT EXISTS UserTmp ($COL_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COL_WEIGHT INTEGER NOT NULL, $COL_GENDER TEXT NOT NULL,$COL_METRIC TEXT NOT NULL, $COL_AGE INTEGER NOT NULL, $COL_WATER INTEGER NOT NULL)")
// Copy the data
database.execSQL("INSERT INTO UserTmp ($COL_ID, $COL_WEIGHT, $COL_GENDER, $COL_METRIC,$COL_AGE, $COL_WATER) SELECT $COL_ID, $COL_WEIGHT, $COL_GENDER, $COL_METRIC,$COL_AGE, $COL_WATER FROM $TABLE_NAME ")
// Remove the old table
database.execSQL("DROP TABLE $TABLE_NAME")
// Change the table name to the correct one
database.execSQL("ALTER TABLE UserTmp RENAME TO $TABLE_NAME")
//COPY DRUNK TABLE
// Create new table
database.execSQL("CREATE TABLE IF NOT EXISTS DrunkTmp ($COL_ID_DRUNK INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COL_DATE_DRUNK TEXT NOT NULL, $COL_TIME_DRUNK TEXT NOT NULL,$COL_DRINK_DRUNK TEXT NOT NULL, $COL_AMOUNT_DRUNK INTEGER NOT NULL ,$COL_METRIC_DRUNK TEXT NOT NULL)")
// Copy the data
database.execSQL("INSERT INTO DrunkTmp ($COL_ID_DRUNK, $COL_DATE_DRUNK, $COL_TIME_DRUNK, $COL_DRINK_DRUNK, $COL_AMOUNT_DRUNK, $COL_METRIC_DRUNK) SELECT $COL_ID_DRUNK, $COL_DATE_DRUNK, $COL_TIME_DRUNK, $COL_DRINK_DRUNK, $COL_AMOUNT_DRUNK, $COL_METRIC_DRUNK FROM $TABLE_NAME_DRUNK")
// Remove the old table
database.execSQL("DROP TABLE $TABLE_NAME_DRUNK")
// Change the table name to the correct one
database.execSQL("ALTER TABLE DrunkTmp RENAME TO $TABLE_NAME_DRUNK")
//COPY NOT TABLE
// Create new table
database.execSQL("CREATE TABLE IF NOT EXISTS NotificationTmp ($COL_ID_NOT INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COL_PREF_NOT INTEGER NOT NULL, $COL_START_NOT INTEGER NOT NULL, $COL_FINISH_NOT INTEGER NOT NULL,$COL_INTERVAL_NOT INTEGER NOT NULL)")
// Copy the data
database.execSQL("INSERT INTO NotificationTmp ($COL_ID_NOT, $COL_PREF_NOT, $COL_START_NOT, $COL_FINISH_NOT, $COL_INTERVAL_NOT) SELECT $COL_ID_NOT, $COL_PREF_NOT, $COL_START_NOT, $COL_FINISH_NOT, $COL_INTERVAL_NOT FROM $TABLE_NAME_NOT ")
// Remove the old table
database.execSQL("DROP TABLE $TABLE_NAME_NOT")
// Change the table name to the correct one
database.execSQL("ALTER TABLE NotificationTmp RENAME TO $TABLE_NAME_NOT")
}
}
fun getDatabase(context: Context?): AppDatabase {
val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
}
synchronized(this) {
val instance = Room.databaseBuilder(
context?.applicationContext!!,
AppDatabase::class.java, DATABASE_NAME
)
.addMigrations(migration_1_2)
.build()
INSTANCE = instance
return instance
}
}
}
}
为用户导出架构
{
"tableName": "User",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `age` INTEGER NOT NULL, `weight` INTEGER NOT NULL, `gender` TEXT NOT NULL, `metric` TEXT NOT NULL, `water` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "age",
"columnName": "age",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "weight",
"columnName": "weight",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "gender",
"columnName": "gender",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "metric",
"columnName": "metric",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "water",
"columnName": "water",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
最后是我收到的错误
java.lang.IllegalStateException: Pre-packaged database has an invalid schema: User(com.afl.waterReminderDrinkAlarmMonitor.model.User).
Expected: TableInfo{name='User', columns={weight=Column{name='weight', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, gender=Column{name='gender', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, metric=Column{name='metric', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, water=Column{name='water', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, age=Column{name='age', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found: TableInfo{name='User', columns={gender=Column{name='gender', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, metric=Column{name='metric', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, weight=Column{name='weight', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, water=Column{name='water', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, age=Column{name='age', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
问题遗漏了预先填充的数据库,该数据库位于 assets
或其他地方;因为不匹配实际上在该文件中并且迁移需要加载它然后更改列。可以看出,table User
列 gender
和 metric
:
的数据类型错误
Expected: TableInfo{name='User', columns={
id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'},
age=Column{name='age', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null',
weight=Column{name='weight', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'},
gender=Column{name='gender', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'},
metric=Column{name='metric', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'},
water=Column{name='water', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}
}}, foreignKeys=[], indices=[]}
Found: TableInfo{name='User', columns={
id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'},
age=Column{name='age', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue ='null',
weight=Column{name='weight', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'},
gender=Column{name='gender', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'},
metric=Column{name='metric', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'},
water=Column{name='water', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}
}}, foreignKeys=[], indices=[]}
在计算机上编辑打包的数据库可能是最省力的。
我正在从 SQlite 迁移到现有应用程序中的房间。因此我创建了迁移策略来创建新的临时表,将现有数据复制到临时表中并删除旧表并重命名新表。
迁移后,我检查了导出的架构,它与预期的架构完全相同,但我仍然收到“发现旧架构并收到以下错误消息”的错误。模式错误的主要区别是“类型”和#notNull“,但我已经在迁移过程中更正了它们
Pre-packaged database has an invalid schema: User(com.afl.waterReminderDrinkAlarmMonitor.model.User)
我的用户实体
@Entity(tableName = "User" )
data class User(
@PrimaryKey
var id: Int = 0,
var age: Int = 0,
var weight: Int = 0,
var gender: String = "",
var metric: String = "",
var water: Int = 0
)
应用数据库
abstract class AppDatabase : RoomDatabase() {
abstract fun dao(): Dao
companion object {
@Volatile
private var INSTANCE: AppDatabase? = null
val migration_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
//COPY USER TABLE
// Create new table
database.execSQL("CREATE TABLE IF NOT EXISTS UserTmp ($COL_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COL_WEIGHT INTEGER NOT NULL, $COL_GENDER TEXT NOT NULL,$COL_METRIC TEXT NOT NULL, $COL_AGE INTEGER NOT NULL, $COL_WATER INTEGER NOT NULL)")
// Copy the data
database.execSQL("INSERT INTO UserTmp ($COL_ID, $COL_WEIGHT, $COL_GENDER, $COL_METRIC,$COL_AGE, $COL_WATER) SELECT $COL_ID, $COL_WEIGHT, $COL_GENDER, $COL_METRIC,$COL_AGE, $COL_WATER FROM $TABLE_NAME ")
// Remove the old table
database.execSQL("DROP TABLE $TABLE_NAME")
// Change the table name to the correct one
database.execSQL("ALTER TABLE UserTmp RENAME TO $TABLE_NAME")
//COPY DRUNK TABLE
// Create new table
database.execSQL("CREATE TABLE IF NOT EXISTS DrunkTmp ($COL_ID_DRUNK INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COL_DATE_DRUNK TEXT NOT NULL, $COL_TIME_DRUNK TEXT NOT NULL,$COL_DRINK_DRUNK TEXT NOT NULL, $COL_AMOUNT_DRUNK INTEGER NOT NULL ,$COL_METRIC_DRUNK TEXT NOT NULL)")
// Copy the data
database.execSQL("INSERT INTO DrunkTmp ($COL_ID_DRUNK, $COL_DATE_DRUNK, $COL_TIME_DRUNK, $COL_DRINK_DRUNK, $COL_AMOUNT_DRUNK, $COL_METRIC_DRUNK) SELECT $COL_ID_DRUNK, $COL_DATE_DRUNK, $COL_TIME_DRUNK, $COL_DRINK_DRUNK, $COL_AMOUNT_DRUNK, $COL_METRIC_DRUNK FROM $TABLE_NAME_DRUNK")
// Remove the old table
database.execSQL("DROP TABLE $TABLE_NAME_DRUNK")
// Change the table name to the correct one
database.execSQL("ALTER TABLE DrunkTmp RENAME TO $TABLE_NAME_DRUNK")
//COPY NOT TABLE
// Create new table
database.execSQL("CREATE TABLE IF NOT EXISTS NotificationTmp ($COL_ID_NOT INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, $COL_PREF_NOT INTEGER NOT NULL, $COL_START_NOT INTEGER NOT NULL, $COL_FINISH_NOT INTEGER NOT NULL,$COL_INTERVAL_NOT INTEGER NOT NULL)")
// Copy the data
database.execSQL("INSERT INTO NotificationTmp ($COL_ID_NOT, $COL_PREF_NOT, $COL_START_NOT, $COL_FINISH_NOT, $COL_INTERVAL_NOT) SELECT $COL_ID_NOT, $COL_PREF_NOT, $COL_START_NOT, $COL_FINISH_NOT, $COL_INTERVAL_NOT FROM $TABLE_NAME_NOT ")
// Remove the old table
database.execSQL("DROP TABLE $TABLE_NAME_NOT")
// Change the table name to the correct one
database.execSQL("ALTER TABLE NotificationTmp RENAME TO $TABLE_NAME_NOT")
}
}
fun getDatabase(context: Context?): AppDatabase {
val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
}
synchronized(this) {
val instance = Room.databaseBuilder(
context?.applicationContext!!,
AppDatabase::class.java, DATABASE_NAME
)
.addMigrations(migration_1_2)
.build()
INSTANCE = instance
return instance
}
}
}
}
为用户导出架构
{
"tableName": "User",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `age` INTEGER NOT NULL, `weight` INTEGER NOT NULL, `gender` TEXT NOT NULL, `metric` TEXT NOT NULL, `water` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "age",
"columnName": "age",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "weight",
"columnName": "weight",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "gender",
"columnName": "gender",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "metric",
"columnName": "metric",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "water",
"columnName": "water",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
最后是我收到的错误
java.lang.IllegalStateException: Pre-packaged database has an invalid schema: User(com.afl.waterReminderDrinkAlarmMonitor.model.User). Expected: TableInfo{name='User', columns={weight=Column{name='weight', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, gender=Column{name='gender', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, metric=Column{name='metric', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, water=Column{name='water', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, age=Column{name='age', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]} Found: TableInfo{name='User', columns={gender=Column{name='gender', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, metric=Column{name='metric', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, weight=Column{name='weight', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, water=Column{name='water', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, age=Column{name='age', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
问题遗漏了预先填充的数据库,该数据库位于 assets
或其他地方;因为不匹配实际上在该文件中并且迁移需要加载它然后更改列。可以看出,table User
列 gender
和 metric
:
Expected: TableInfo{name='User', columns={
id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'},
age=Column{name='age', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null',
weight=Column{name='weight', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'},
gender=Column{name='gender', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'},
metric=Column{name='metric', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'},
water=Column{name='water', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}
}}, foreignKeys=[], indices=[]}
Found: TableInfo{name='User', columns={
id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'},
age=Column{name='age', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue ='null',
weight=Column{name='weight', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'},
gender=Column{name='gender', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'},
metric=Column{name='metric', type='VARCHAR(256)', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'},
water=Column{name='water', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}
}}, foreignKeys=[], indices=[]}
在计算机上编辑打包的数据库可能是最省力的。