Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ / /

更改对象模型 - Kotlin SDK

在此页面上

  • Overview
  • 模式版本
  • 迁移
  • 自动更新模式
  • 添加属性
  • 删除属性
  • 手动迁移模式
  • 修改属性
  • 其他迁移任务

注意

修改同步 Realm 的模式属性

以下页面演示了如何修改本地域的模式属性。 了解如何修改同步域的模式属性。

创建 Realm 对象模型后,您可以更改对象模式。 根据您对模式所做的更改类型,可以自动应用更改或需要手动更新到新模式。

  • 当您在 Realm 对象模型中添加或删除属性时,Realm 会自动更新 Realm对象模式。 您只需更新模式版本。

  • 对于所有其他模式更改,您必须手动将给定对象的旧实例迁移到新模式。

提示

在开发期间绕过迁移

在开发或调试应用程序时,您可能更愿意删除域不是迁移 Realm。 使用deleteRealmIfMigrationNeeded标志在模式不匹配需要迁移时自动删除数据库。

切勿将此标志设置为 true的应用程序发布到生产环境。

模式版本可标识 Realm 模式在某个时间点的状态。Realm 会跟踪每个 Realm 的模式版本,并使用该信息将每个 Realm 中的对象映射到正确的模式。

模式版本是指打开Realm 时可以选择包含在 Realm 配置中的递增整数。 如果客户端应用程序在打开 Realm 时未指定版本号,则该 Realm 默认采用0版本。

重要

单调递增版本

迁移必须将 Realm 更新到更高的模式版本。 如果客户端应用程序打开的 Realm 的模式版本低于该 Realm 的当前版本,或者指定的模式版本与该 Realm 的当前版本相同但包含不同的对象模式,Realm 则会引发错误。

模式更新在 Realm 中称为迁移。 迁移将域及其包含的任何对象从一个模式版本更新到较新的版本。

每当您打开模式版本高于该 Realm 当前版本的现有 Realm 时,您都可以提供一个迁移函数来定义模式更新所需的任何其他逻辑。 例如:

  • 设置属性值

  • 合并或拆分字段

  • 重命名字段

  • 更改字段的类型

该函数可访问域的版本号并以递增方式更新域中的对象以符合新模式。

本地迁移是针对不会自动与另一个 Realm同步的 Realm 的迁移。

注意

要修改同步 Realm 的模式属性,请参阅 Atlas Device Sync 文档中的更新数据模型

如果您的模式更新添加或删除了属性,Realm 可以自动执行迁移。 您只需递增schemaVersion即可。

要向在模式中添加属性,请执行以下操作:

  1. 将新属性添加到RealmObject定义中。

  2. 通过RealmConfiguration构建器设置模式版本。

如果更新的对象模式指定了默认值, Realm会自动为新属性设置值。 如果更新后的对象模式未指定默认值,则必须通过迁移函数手动为新属性设立值。

例子

使用模式版本1 Person的域具有带有名字、姓氏和年龄属性的Realm 对象类型:

// Realm schema version 1
class Person : RealmObject {
var firstName: String = ""
var lastName: String = ""
var age: Int = 0
}

开发者将email字段添加到Person类中:

// Realm schema version 2
class Person : RealmObject {
var firstName: String = ""
var lastName: String = ""
var age: Int = 0
var email: String? = null
}

要更改 Realm 以符合更新的Person模式,开发者将 Realm 的模式版本设置为2

val config = RealmConfiguration.Builder(
schema = setOf(Person::class)
)
.schemaVersion(2) // Sets the new schema version to 2
.build()
val realm = Realm.open(config)

要从模式中删除属性,请执行以下操作:

  1. 从对象的类中删除该属性。

  2. 通过RealmConfiguration构建器设置模式版本。

删除属性不会影响现有的对象。

例子

使用 模式版本的2 Person域 有一个Realm 对象类型,其中包含名字、姓氏、年龄和电子邮件属性:

// Realm schema version 2
class Person : RealmObject {
var firstName: String = ""
var lastName: String = ""
var age: Int = 0
var email: String? = null
}

开发者从Person类中删除age字段:

// Realm schema version 3
class Person : RealmObject {
var firstName: String = ""
var lastName: String = ""
// var age: Int = 0
var email: String? = null
}

要更改 Realm 以符合更新的Person模式,开发者将 Realm 的模式版本设置为3

val config = RealmConfiguration.Builder(
schema = setOf(Person::class)
)
.schemaVersion(3) // Sets the new schema version to 3
.build()
val realm = Realm.open(config)

对于更复杂的模式更新,Realm 要求您手动将给定对象的旧实例迁移到新模式。

当您使用更新的模式打开 Realm 时,您必须在RealmConfiguration 中执行以下操作:

要修改对象属性(例如 重命名、合并、分割或更改属性类型):

  1. 更改对象模式中的一个或多个属性。

  2. 打开具有递增模式版本和映射现有对象以使用新属性的迁移函数的 域。

在以下示例中,更新模式以更改属性类型、将两个属性合并为新属性以及重命名现有属性:

// Realm schema version 1 (oldObject)
class Person : RealmObject {
var _id: ObjectId = ObjectId()
var firstName: String = ""
var lastName: String = ""
var age: Int = 0
}
// Realm schema version 2 (newObject)
class Person : RealmObject {
var _id: String = "" // change property type
var fullName: String = "" // merge firstName and lastName properties
var yearsSinceBirth: Int = 0 // rename property
}

然后,迁移函数定义迁移逻辑,以在旧对象模式和新对象模式中修改的属性之间映射数据:

// Use the configuration builder to open the realm with the newer schema version
// and define the migration logic between your old and new realm objects
val config = RealmConfiguration.Builder(
schema = setOf(Person::class)
)
.schemaVersion(2) // Set the new schema version to 2
.migration(AutomaticSchemaMigration {
it.enumerate(className = "Person") { oldObject: DynamicRealmObject, newObject: DynamicMutableRealmObject? ->
newObject?.run {
// Change property type
set(
"_id",
oldObject.getValue<ObjectId>(fieldName = "_id").toString()
)
// Merge properties
set(
"fullName",
"${oldObject.getValue<String>(fieldName = "firstName")} ${oldObject.getValue<String>(fieldName = "lastName")}"
)
// Rename property
set(
"yearsSinceBirth",
oldObject.getValue<String>(fieldName = "age")
)
}
}
})
.build()
val realm = Realm.open(config)

注意

如果您的模式更新包括将RealmObject转换为EmbeddedRealmObject ,则迁移函数必须确保该嵌入式对象确切地链接有一个父对象。 嵌入式对象不能独立于父对象而存在。

要执行其他域模式迁移,请使用AutomaticSchemaMigration.MigrationContext接口的以下属性:

  • oldRealm :上一模式版本迁移之前存在的 Realm。 动态API 允许您通过类名称的 表示形式查找Realm string对象。

  • newRealm :使用新模式版本迁移后存在的域 。

oldRealmnewRealm获取的任何对象仅在迁移函数的范围内有效。

迁移结束时,您必须将受模式更新影响的所有数据从旧 Realm 迁移到新 Realm。 任何受模式更新影响但未迁移的数据都将丢失。

val config = RealmConfiguration.Builder(
schema = setOf(Person::class)
)
.schemaVersion(2)
.migration(AutomaticSchemaMigration { migrationContext ->
val oldRealm = migrationContext.oldRealm // old realm using the previous schema
val newRealm = migrationContext.newRealm // new realm using the new schema
// Dynamic query for all Persons in old realm
val oldPersons = oldRealm.query(className = "Person").find()
for (oldPerson in oldPersons) {
// Get properties from old realm
val firstName: String = oldPerson.getValue(
propertyName = "firstName", String::class
)
// Get objects from old realm as dynamic realm objects
val pet: DynamicRealmObject? = oldPerson.getObject(
propertyName = "pets"
)
}
// Get migrated objects from the new realm as mutable objects
val oldPerson: DynamicMutableRealmObject? =
newRealm.findLatest(oldPersons[0])
oldPerson?.let {
it.set("fullName", "Crow T. Robot")
}
// Create an object in the new realm and set property values
val newPerson = newRealm.copyToRealm(
DynamicMutableRealmObject.create(
type = "Person",
mapOf(
"_id" to "123456",
"fullName" to "Tom Servo",
"yearsSinceBirth" to 33,
)
)
)
})
.build()
val realm = Realm.open(config)

后退

地理空间数据