如何将 Room 数据库从 1 迁移到 2?
我正在尝试将我的 Room 数据库迁移到下一个版本,但我不断收到相同的错误:
java.lang.IllegalStateException: A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.
我的数据库版本之间的唯一区别是我添加了一个新列。迁移是这样处理的:
@Database(
version = 2,
entities = [Note::class],
exportSchema = true)
abstract class AppDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDAO
companion object {
fun build(context: Context) = Room.databaseBuilder(context, AppDatabase::class.java, "NotesDatabase")
.addMigrations(MIGRATION_1_2).build()
}
}
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Notes ADD COLUMN image STRING")
}
}
我不确定我是否正确实现了这一点。该错误告诉我必须以某种方式调用 .build()。我在使用数据库的活动中尝试了这一点,但错误是相同的,因此我删除了该调用。
我该如何解决这个问题?
I'm trying to migrate my Room db to the next version and I keep getting the same error:
java.lang.IllegalStateException: A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.
The only difference between my database versions is that I have added a new column. The migration is handled like this:
@Database(
version = 2,
entities = [Note::class],
exportSchema = true)
abstract class AppDatabase : RoomDatabase() {
abstract fun noteDao(): NoteDAO
companion object {
fun build(context: Context) = Room.databaseBuilder(context, AppDatabase::class.java, "NotesDatabase")
.addMigrations(MIGRATION_1_2).build()
}
}
val MIGRATION_1_2 = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Notes ADD COLUMN image STRING")
}
}
I'm not sure if I have implemented that correctly. The error tells me that I have to somehow call .build(). I tried that in the activity using the database, but the error was the same so I removed that call.
How can I fix this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看来您没有调用构建函数,并且可能有另一种构建数据库的方法(调用databaseBuilder)。
例如,在活动/片段中,您有类似的内容:-
在更改 Note 实体并将版本增加到 2 后会产生结果,例如:-
相反,您需要调用 AppDatabase 的构建函数,
因此上面的内容将变为:-
但是,然后您将收到类似以下内容的预期/发现问题:-
这是因为就房间而言,STRING 不是有效的列类型。
在上面你可以看到/提取 room 期望的:-
BUT Room 找到:-
Room 只接受 INTEGER、REAL、TEXT 和 BLOB 的列类型(尽管 SQLite 在列类型方面更加灵活) 。
类型取决于变量的类型,此外 Room 对于定义的其他部分也非常具体,例如 NOT NULL 是否应该成为定义的一部分以及 DEFAULT 是否应该成为定义的一部分。
但是,Room 允许您准确确定列定义应该是什么。如果您对实体进行更改并编译项目,则 Room 会生成 java 代码,其中包括用于创建表的 SQL,并且在此 SQL 中是预期的列定义。
从 Android Studio 项目视图中,您将看到
Java(生成)
,在此下的类/文件中将包含一些类,其中之一是 AppDatabase_Impl。在这个类中将有一个方法createAlltables。此方法中包含所有表的 SQL。例如:-
var image: String
但是,如果 ALTER 一个表并添加一个 NOT NULL 列,那么 SQLite 要求提供一个不为空的 DEFAULT,按照: - fa NOT NULL 约束被指定,那么该列必须有NULL 以外的默认值。 https://www.sqlite.org/lang_altertable.html
因此,在上面的情况下,如果发现的结果是 room 所期望的,那么 ALTER SQL 应该是:-
'unknown' 可以是任何适合的内容
It appears that you are not invoking the build function and probably have another means of building the database (invoking the databaseBuilder).
e.g. In an activity/fragment you have something like :-
This after changing the Note entity and increasing the version to 2 yields the results e.g. :-
Instead you need to invoke the AppDatabase's build function
So the above would become :-
HOWEVER, you will then get the Expected/Found issue something like :-
This is because STRING, as far as room is concerned, is not a valid column type.
In the above you can see/extract that room expects :-
BUT Room found :-
Room only accepts column types of INTEGER, REAL, TEXT and BLOB (even though SQLite is far more flexible with column types).
The type depends upon the type of the variable, furthermore Room is also very specific about other parts of the definition, such as whether or not NOT NULL should be part and whether or not DEFAULT should be part of the definition or not.
However, Room allows you to ascertain exactly what the column definition should be. If you make the changes to the entity(ies) and compile the project then java code is generated by Room, this includes the SQL used to create the table(s) and within this SQL are the expected column definitions.
From the Android Studio Project View you will see
Java (generated)
, within the classes/files under this will be some classes one of which will be AppDatabase_Impl. Within this class there will be a method createAlltables. Within this method is the SQL for all the tables.e.g. :-
var image: String
However, if ALTERing a table and adding a column with NOT NULL then SQLite requires that a DEFAULT is provided that is not null, as per:- f a NOT NULL constraint is specified, then the column must have a default value other than NULL. https://www.sqlite.org/lang_altertable.html
So in the case above then for the found to be what room expects then the ALTER SQL should be :-
'unknown'
could be whatever suits