我在用FTS4与Room与这两个实体。
@Entity(tableName = "persons")
data class Person(
@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") val id: Long,
@ColumnInfo(name = "name") val name: String,
@ColumnInfo(name = "employed") val employed: Boolean)
@Fts4(contentEntity = Person::class)
@Entity(tableName = "persons_fts")
data class PersonFts(
@PrimaryKey @ColumnInfo(name = "rowid")val rowid: Long,
@ColumnInfo(name = "name") val name: String)
现在让我们假设,由于目前的危机,每个人都失去了工作,而这两个实体: employed
列不再需要了,因为没有人被雇用。我想通过删除该列来迁移我的数据库。这是迁移语句。
CREATE TABLE persons_temp (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL)
INSERT INTO persons_temp (id, name) SELECT id, name FROM persons
DROP TABLE persons
ALTER TABLE persons_temp RENAME TO persons
我想测试一下 androidx.room:room-testing
所以我创建了一个简单的测试,只是验证模式。
@RunWith(AndroidJUnit4::class)
class MigrationTest {
@get:Rule
val helper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
MyDatabase::class.java.canonicalName,
FrameworkSQLiteOpenHelperFactory())
@Test
@Throws(IOException::class)
fun migrate1To2() {
// Just let the helper validate the schema changes.
helper.createDatabase("migration-test", 1)
helper.runMigrationsAndValidate("migration-test", 2, true, MyDatabase.MIGRATION_1_2)
}
}
但是测试失败,出现了这样的错误
java.lang.IllegalStateException: Migration didn't properly handle: persons_fts
Expected: FtsTableInfo{name='persons_fts', columns=[name, rowid], options=[content=`persons`]}
Found: FtsTableInfo{name='persons_fts', columns=[name], options=[content=`persons`]}
由于某种原因,FTS表丢失了它的... rowid
列。但根据 文件在迁移过程中,触发器应该被移除,所以FTS表应该不受影响。这里的问题是什么?
其实我在写问题的时候已经找到了解决这个问题的方法,所以我想还是把它贴出来。通过删除 rowid
属性,测试就通过了。
@Fts4(contentEntity = Person::class)
@Entity(tableName = "persons_fts")
data class PersonFts(
@ColumnInfo(name = "name") val name: String)
文档中说 rowid
属性是可选的,即使被省略,也会在查询中可用。然而,通过定义它,生成的模式是不同的,它有一个 rowid
列,如果省略该属性,则不存在。我相信这就是迁移测试失败的原因。我不太确定这是否是一个错误。