Room 如何通过数据库迁移实现首次显式创建所有表?
Room 手动显式创建数据库表操作方案
方案一:通过迁移实现(更推荐,和后续升级逻辑统一)
这种方式把初始建表作为从版本0到初始版本的迁移处理,完全由你自主控制所有建表SQL,全程不依赖Room默认建表逻辑:
- 首先编写初始版本迁移逻辑,将所有你需要的建表、建索引、加约束的SQL都写在迁移实现中:
// 示例为从版本0升级到版本1的迁移,即空库初始化逻辑 val MIGRATION_0_1 = object : Migration(0, 1) { override fun migrate(database: SupportSQLiteDatabase) { // 自行编写所有建表语句,完全自主控制表结构、约束、索引 database.execSQL("CREATE TABLE IF NOT EXISTS `user` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `username` TEXT NOT NULL, `mobile` TEXT UNIQUE NOT NULL)") database.execSQL("CREATE TABLE IF NOT EXISTS `order` (`order_id` TEXT PRIMARY KEY NOT NULL, `user_id` INTEGER NOT NULL, `amount` INTEGER NOT NULL, FOREIGN KEY(`user_id`) REFERENCES `user`(`id`) ON DELETE CASCADE)") database.execSQL("CREATE INDEX IF NOT EXISTS `index_order_user_id` ON `order` (`user_id`)") // 其余表的创建语句依次添加即可 } }
- 在Room数据库构建时注册上述迁移即可:
val appDatabase = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "你的数据库名称" ) .addMigrations(MIGRATION_0_1) // 禁止破坏性重建,避免异常时清空数据 .build()
方案二:通过自定义Room Callback实现
如果你不需要和后续迁移逻辑统一管理,可以重写Room初始化回调禁用默认建表逻辑,自行执行建表语句:
- 自定义RoomDatabase.Callback,重写
onCreate方法,不调用父类实现,写入自定义建表逻辑:
val customDbCallback = object : RoomDatabase.Callback() { override fun onCreate(db: SupportSQLiteDatabase) { // 不调用super.onCreate(),即可禁用Room默认按实体生成表的逻辑 // 执行自行编写的所有建表SQL db.execSQL("CREATE TABLE IF NOT EXISTS `user` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `username` TEXT NOT NULL, `mobile` TEXT UNIQUE NOT NULL)") // 其余表、索引、约束创建语句依次添加 } override fun onOpen(db: SupportSQLiteDatabase) { super.onOpen(db) // 如需开启外键约束可以在这里配置 db.setForeignKeyConstraintsEnabled(true) } }
- 在Room数据库构建时注册该回调:
val appDatabase = Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, "你的数据库名称" ) .addCallback(customDbCallback) .build()
注意事项
- 你自行编写的建表语句结构必须和你定义的Room实体类的字段名、字段类型、非空约束、主键/外键规则完全匹配,否则Room运行时会触发Schema校验异常
- 后续数据库版本升级的迁移逻辑完全由你自行编写SQL实现,无需依赖Room自动生成的Schema文件,可实现100%自主控制Schema迭代
内容的提问来源于stack exchange,提问作者James Bond
相关产品推荐
相关产品推荐

