更新时间:2022-10-17 16:53:36
Room 确实没有有一个好的迁移系统,至少在 2.1.0 之前没有-alpha03
.
Room does NOT have a good Migration System, at least not until 2.1.0-alpha03
.
因此,在我们拥有更好的迁移系统之前,有一些解决方法可以在房间中轻松迁移.
So, until we have better Migration System, there are some workarounds to have easy Migrations in the Room.
因为没有像 @Database(createNewTables = true)
或 MigrationSystem.createTable(User::class)
这样的方法,应该有一个或另一个,唯一可能的方法是运行
As there is no such method as @Database(createNewTables = true)
or MigrationSystem.createTable(User::class)
, which there should be one or other, the only possible way is running
CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))
在您的 migrate
方法中.
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))")
}
}
为了获得上述 SQL 脚本,您有 4 种方法
In order to get above SQL script, you have 4 ways
基本上,您必须编写与 Room 生成的脚本匹配的上述脚本.这种方式可行,不可行.(假设您有 50 个字段)
Basically, you have to write the above script that will match the script that Room generates. This way is possible, not feasible. (Consider you have 50 fields)
如果在 @Database
注释中包含 exportSchema = true
,Room 将在项目文件夹的/schemas 中生成数据库模式.用法是
If you include exportSchema = true
inside your @Database
annotation, Room will generate database schema within /schemas of your project folder. The usage is
@Database(entities = [User::class], version = 2, exportSchema = true)
abstract class AppDatabase : RoomDatabase {
//...
}
确保您在应用模块的 build.grade
中包含以下几行
Make sure that you have included below lines in build.grade
of your app module
kapt {
arguments {
arg("room.schemaLocation", "$projectDir/schemas".toString())
}
}
当您运行或构建项目时,您将获得一个 JSON 文件 2.json
,其中包含 Room 数据库中的所有查询.
When you run or build the project you will get a JSON file 2.json
, which has all the queries within your Room database.
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "325bd539353db508c5248423a1c88c03",
"entities": [
{
"tableName": "User",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
因此,您可以在 migrate
方法中包含上述 createSql
.
So, you can include the above createSql
within you migrate
method.
如果您不想导出架构,您仍然可以通过运行或构建将生成 AppDatabase_Impl.java
文件的项目来获取查询.并在您可以拥有的指定文件中.
If you don't want to export schema you can still get the query by running or building the project which will generate AppDatabase_Impl.java
file. and within the specified file you can have.
@Override
public void createAllTables(SupportSQLiteDatabase _db) {
_db.execSQL("CREATE TABLE IF NOT EXISTS `User` (`id` INTEGER, PRIMARY KEY(`id`))");
在createAllTables
方法中,会有所有实体的创建脚本.您可以获取它并包含在您的 migrate
方法中.
Within createAllTables
method, there will be the create scripts of all the entities. You can get it and include in within you migrate
method.
正如您可能猜到的,Room 会在编译时间内生成所有上述 schema
和 AppDatabase_Impl
文件,并使用您添加的注释处理
As you might guess, Room generates all of the above mentioned schema
, and AppDatabase_Impl
files within compilation time and with Annotation Processing which you add with
kapt "androidx.room:room-compiler:$room_version"
这意味着您也可以做同样的事情,制作自己的注释处理库,为您生成所有必要的创建查询.
That means you can also do the same and make your own annotation processing library that generates all the necessary create queries for you.
想法是为@Entity
和@Database
的Room注解做一个注解处理库.以一个用 @Entity
注释的类为例.这些是您必须遵循的步骤
The idea is to make an annotation processing library for Room annotations of @Entity
and @Database
. Take a class that is annotated with @Entity
for example. These are the steps you will have to follow
StringBuilder
并附加CREATE TABLE IF NOT EXISTS"class.simplename
或@Entity
的tableName
字段获取表名.将它添加到您的 StringBuilder
@ColumnInfo
注释获取字段的名称、类型、可为空性.对于每个字段,您必须将列的 id INTEGER NOT NULL
样式添加到您的 StringBuilder
.@PrimaryKey
ForeignKey
和Indices
(如果存在).StringBuilder
and append "CREATE TABLE IF NOT EXISTS "class.simplename
or by tableName
field of @Entity
. Add it to your StringBuilder
@ColumnInfo
annotation.
For every field, you have to add id INTEGER NOT NULL
style of a column to your StringBuilder
.@PrimaryKey
ForeignKey
and Indices
if exists.public final class UserSqlUtils {
public String createTable = "CREATE TABLE IF NOT EXISTS User (id INTEGER, PRIMARY KEY(id))";
}
然后,您可以将其用作
val MIGRATION_1_2 = object : Migration(1, 2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL(UserSqlUtils().createTable)
}
}
我为自己制作了这样一个库,您可以查看它,甚至在您的项目中使用它.请注意,我制作的库并不完整,它只是满足了我创建表的要求.
I made such a library for myself which you can check out, and even use it in your project. Note that the library that I made is not full and it just fulfills my requirements for table creation.
希望有用.
在撰写此答案时,房间版本为 2.1.0-alpha03
,当我给开发人员发送电子邮件时,我收到了
By the time of writing this answer, room version was 2.1.0-alpha03
and when I emailed developers I got a response of
2.2.0
不幸的是,我们仍然缺乏更好的迁移系统.
Unfortunately, we still lack better Migration System.