Room数据库迁移异常:appointment表未正确处理问题求助
Android Room迁移错误修复:Migration didn't properly handle appointment实体
错误概述
使用Android Room数据库时触发以下错误:
java.lang.IllegalStateException: Migration didn't properly handle: appointment(com.example.spaappointment.data.Appointment).
错误日志显示:Room预期appointment表包含完整字段,但实际检测到表为空(columns={})。
Appointment实体类代码
package com.example.spaappointment.data import androidx.annotation.NonNull import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey @Entity(tableName = "appointment") data class Appointment( @NonNull @PrimaryKey val date: String, @ColumnInfo val name: String, @NonNull @ColumnInfo val phonenumber: Int, @NonNull @ColumnInfo val email: String, @ColumnInfo val note: String )
数据库Schema(版本3)
{ "formatVersion": 1, "database": { "version": 3, "identityHash": "939188bd3f343aa9fe8319733e41e36a", "entities": [ { "tableName": "service", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`price`TEXT NOT NULL,`name`TEXT NOT NULL,`description`TEXT NOT NULL,`id` INTEGER NOT NULL, PRIMARY KEY(`id`))", "fields": [ { "fieldPath": "price", "columnName": "price", "affinity": "TEXT", "notNull": true }, { "fieldPath": "name", "columnName": "name", "affinity": "TEXT", "notNull": true }, { "fieldPath": "description", "columnName": "description", "affinity": "TEXT", "notNull": true }, { "fieldPath": "id", "columnName": "id", "affinity": "INTEGER", "notNull": true } ], "primaryKey": { "columnNames": ["id"], "autoGenerate": false }, "indices": [], "foreignKeys": [] }, { "tableName": "appointment", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`date`TEXT NOT NULL,`name`TEXT NOT NULL,`phonenumber`INTEGER NOT NULL,`email`TEXT NOT NULL,`note` TEXT NOT NULL, PRIMARY KEY(`date`))", "fields": [ { "fieldPath": "date", "columnName": "date", "affinity": "TEXT", "notNull": true }, { "fieldPath": "name", "columnName": "name", "affinity": "TEXT", "notNull": true }, { "fieldPath": "phonenumber", "columnName": "phonenumber", "affinity": "INTEGER", "notNull": true }, { "fieldPath": "email", "columnName": "email", "affinity": "TEXT", "notNull": true }, { "fieldPath": "note", "columnName": "note", "affinity": "TEXT", "notNull": true } ], "primaryKey": { "columnNames": ["date"], "autoGenerate": false }, "indices": [], "foreignKeys": [] } ], "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '939188bd3f343aa9fe8319733e41e36a')" ] } }
完整错误日志
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.spaappointment, PID: 9952 java.lang.IllegalStateException: Migration didn't properly handle: appointment(com.example.spaappointment.data.Appointment). Expected: TableInfo{name='appointment', columns={date=Column{name='date', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, name=Column{name='name', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, phonenumber=Column{name='phonenumber', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, note=Column{name='note', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, email=Column{name='email', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]} Found: TableInfo{name='appointment', columns={}, foreignKeys=[], indices=[]}
修复方案
1. 补全迁移脚本中的表创建逻辑
检查你的Migration类,确保对应版本升级时执行了appointment表的创建语句,语句需和Schema中的createSql完全一致:
val MIGRATION_2_3 = object : Migration(2, 3) { override fun migrate(database: SupportSQLiteDatabase) { // 确保创建appointment表的语句与Schema完全匹配 database.execSQL(""" CREATE TABLE IF NOT EXISTS `appointment` ( `date` TEXT NOT NULL, `name` TEXT NOT NULL, `phonenumber` INTEGER NOT NULL, `email` TEXT NOT NULL, `note` TEXT NOT NULL, PRIMARY KEY(`date`) ) """) // 如果还有其他表的变更,也要添加对应SQL } }
2. 确认数据库配置正确
- 在RoomDatabase子类中,确保版本号设置为3,并且注册了迁移脚本:
@Database(entities = [Appointment::class, Service::class], version = 3) abstract class SpaDatabase : RoomDatabase() { // 定义DAO接口 abstract fun appointmentDao(): AppointmentDao abstract fun serviceDao(): ServiceDao }
- 初始化数据库时必须添加迁移脚本:
val db = Room.databaseBuilder( context.applicationContext, SpaDatabase::class.java, "spa_database" ) .addMigrations(MIGRATION_2_3) // 注册迁移脚本 .build()
3. 排查是否误删表
检查迁移代码中是否存在DROP TABLE appointment之类的语句,若有则移除,避免表被意外删除。
4. 开发环境临时方案(数据会丢失)
如果是开发阶段,可使用破坏性迁移快速验证,Room会删除旧数据库并重建新的:
val db = Room.databaseBuilder(...) .fallbackToDestructiveMigration() .build()
内容的提问来源于stack exchange,提问作者Duaa Alyamani
相关产品推荐
相关产品推荐

