原文:https://docs.mongodb.com/realm/sdk/android/examples/define-a-realm-object-model
文章目录
定义一个 Realm 对象
要在您的应用程序中定义 Realm 对象,请创建 RealmObject 的子类或实现RealmModel。
所有 Realm 对象都必须提供一个空的构造函数。
继承 RealmObject
例子
以下代码块展示了一个描述 Frog 的 Realm 对象。这个 Frog 类可以存储在 Realm 数据库中,因为它继承了 RealmObject 类。
import io.realm.RealmObject
// providing default values for each constructor parameter
// fulfills the need for an empty constructor
open class Frog(
var name: String? = null,
var age: Int = 0,
var species: String? = null,
var owner: String? = null
) : RealmObject() // To add an object to your Realm Schema, extend RealmObject
所有定义的 Realm 对象都必须使用 open 可见性修饰符。
实现 RealmModel
例子
以下代码块展示了一个描述青蛙的 Realm 对象。这个 Frog 类可以存储在 Realm 数据库中,因为它 实现了 RealmModel 类并且使用了@RealmClass 注解:
import io.realm.RealmModel
import io.realm.annotations.RealmClass
@RealmClass
open class Frog : RealmModel {
var name: String? = null
var age = 0
var species: String? = null
var owner: String? = null
constructor(name: String?, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
所有 Realm 对象都必须使用 open 可见性修饰符。
使用 RealmObject 方法
当您通过继承 RealmObject 类创建 Realm 对象时,您可以在 Realm 对象的实例上动态访问 RealmObject 类方法。通过实现 RealmModel 创建的 Realm 对象可以通过RealmObject 类静态访问这些相同的方法:
// With RealmObject
frogRealmObject?.isValid
frogRealmObject?.addChangeListener(listener)
// With RealmModel
RealmObject.isValid(frogRealmModel)
RealmObject.addChangeListener(frogRealmModel, listener)
Lists 列表
Realm 对象可以包含非 Realm 对象数据类型的列表:
import io.realm.RealmList
import io.realm.RealmObject
open class Frog : RealmObject {
var name: String? = null
var age = 0
var species: String? = null
var owner: String? = null
var favoriteColors : RealmList<String>? = null
constructor(
name: String?,
age: Int,
species: String?,
owner: String?,
favoriteColors: RealmList<String>?
) {
this.name = name
this.age = age
this.species = species
this.owner = owner
this.favoriteColors = favoriteColors
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
定义关系字段
多对一
要设置多对一或一对一关系,请在应用程序中创建一个类型为 Realm 对象的字段:
import io.realm.RealmObject
open class Frog : RealmObject {
var name: String? = null
var age = 0
var species: String? = null
var owner: String? = null
var bestFriend: Frog? = null
constructor(
name: String?,
age: Int,
species: String?,
owner: String?,
bestFriend: Frog?
) {
this.name = name
this.age = age
this.species = species
this.owner = owner
this.bestFriend = bestFriend
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
每个 Frog 都引用零个 Frog 实例或一个其他 Frog 实例。没有什么可以阻止多个 Frog 实例引用同一个 Frog 实例作为最好的朋友;多对一和一对一关系之间的区别取决于您的应用程序。
多对多
import io.realm.RealmList
import io.realm.RealmObject
open class Frog : RealmObject {
var name: String? = null
var age = 0
var species: String? = null
var owner: String? = null
var bestFriends: RealmList<Frog>? = null
constructor(
name: String?,
age: Int,
species: String?,
owner: String?,
bestFriends: RealmList<Frog>?
) {
this.name = name
this.age = age
this.species = species
this.owner = owner
this.bestFriends = bestFriends
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
RealmLists 是 RealmObject 的容器,但其他方面的行为就像一个常规集合。您可以在多个 RealmLists 中使用同一个对象 。
逆关系
默认情况下, Realm 数据库关系是单向的。您可以沿着链接从一个类到一个引用类,但不能沿着相反的方向。考虑以下定义一个有 frogFriends 列表的 Toada 类 :
import io.realm.RealmList
import io.realm.RealmObject
open class Toad : RealmObject {
var frogFriends: RealmList<Frog>? = null
constructor(frogFriends: RealmList<Frog>?) {
this.frogFriends = frogFriends
}
constructor() {}
}
您可以提供相反方向的链接,从 Frog 到Toad, 在 final(Java 中)或 val(Kotlin 中)的 RealmResults<T> 类型字段上带有 @LinkingObjects 注解:
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.LinkingObjects
open class Frog : RealmObject {
var name: String? = null
var age = 0
var species: String? = null
var owner: String? = null
@LinkingObjects("frogFriends")
private val toadFriends: RealmResults<Toad>? = null
constructor(name: String?, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
反向关系字段必须标记 final / val。
定义嵌入对象字段
Realm 数据库提供了在其他对象中嵌套对象的能力。这有几个优点:
- 如果使用 Realm Sync,对象将转换为遵循非规范化数据模型的 MongoDB 文档。
- 当您删除包含另一个对象的对象时,删除操作会将两个对象从 Realm 中删除,因此未使用的对象不会累积在您的 Realm 文件中,从而占用用户移动设备上的宝贵空间。
要嵌入对象,请在您想要嵌套在另一个类中的类的 @RealmClass 注释中将 embedded 属性设置 true :
import io.realm.RealmObject
import io.realm.annotations.RealmClass
@RealmClass(embedded = true)
open class Fly : RealmObject {
private var name: String? = null
constructor(name: String?) {
this.name = name
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
然后,每当您从另一个类引用该类时,Realm 数据库都会将引用的类嵌入到封闭类中,如下例所示:
import io.realm.RealmObject
open class Frog : RealmObject {
var name: String? = null
var age = 0
var species: String? = null
var owner: String? = null
var lastMeal: Fly? = null
constructor(
name: String?,
age: Int,
species: String?,
owner: String?,
lastMeal: Fly?
) {
this.name = name
this.age = age
this.species = species
this.owner = owner
this.lastMeal = lastMeal
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
Annotations 注解
使用注解来自定义你的 Realm 对象模型。
Primary Key 主键
您可以选择性地通过 @PrimaryKey 注解为一个对象类型定义一个主键,来作为对象模式的一部分:
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
open class Frog : RealmObject {
@PrimaryKey var name : String? = null
var age = 0
var species: String? = null
var owner: String? = null
constructor(name: String?, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
RealmObject 中只有一个字段可以使用 @PrimaryKey 注解。
Required Fields 必需字段
import io.realm.RealmObject
import io.realm.annotations.Required
open class Frog : RealmObject {
@Required var name: String? = null
var age = 0
var species: String? = null
var owner: String? = null
constructor(name: String?, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
Optional Fields 可选字段
字段只有在它们可以保存值 null 并且没有用 Required 注解标记时才是可选的。
Default Field Values 字段默认值
要为字段分配默认值,请使用内置语言功能分配默认值。
科特林
爪哇
在字段声明中分配默认值:
import io.realm.RealmObject
open class Frog : RealmObject {
var name = "Kitty"
var age = 0
var species: String? = null
var owner: String? = null
constructor(name: String, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
默认值和可空性
虽然默认值确保新创建的对象不能包含值 null(除非您指定默认值 null),但它们不会影响字段的可空性。要使字段不可为空,请参阅必需字段。
Index a Field 索引一个字段
要索引字段,请使用 @Index 注解:
import io.realm.RealmObject
import io.realm.annotations.Index
open class Frog : RealmObject {
var name: String? = null
var age = 0
@Index var species : String? = null
var owner: String? = null
constructor(name: String?, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
Ignore a Field 忽略字段
如果不想将模型中的字段保存到 Realm,则可以忽略字段。
使用 @Ignore 注解忽略 Realm 对象模型中的字段:
import io.realm.RealmObject
import io.realm.annotations.Ignore
open class Frog : RealmObject {
var name: String? = null
var age = 0
var species: String? = null
// can you ever really own a frog persistently?
@Ignore var owner : String? = null
constructor(name: String?, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
忽略 static 和 transient 字段
标记为 static 或 transient 的字段总是被忽略,不需要 @Ignore 注解。
Rename a Field 重命名字段
默认情况下,Realm 数据库使用模型类中定义的名称在内部表示字段。在某些情况下,您可能希望更改此行为:
- 为了更轻松地跨平台工作,因为命名约定不同。
- 在 Kotlin 中更改字段名称而不强制迁移。
选择与模型类中使用的名称不同的内部名称具有以下含义:
- 创建类和字段时,迁移必须使用内部名称。
- 模式错误报告将使用内部名称。
使用 @RealmField 注解重命名字段:
import io.realm.RealmObject
import io.realm.annotations.RealmField
open class Frog : RealmObject {
var name: String? = null
var age = 0
@RealmField("latinName") var species: String? = null
var owner: String? = null
constructor(name: String?, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
或者,您还可以在模块或类级别分配命名策略,以更改 Realm 数据库解释字段名称的方式。
您可以在模块级别定义命名策略,这将影响模块中包含的所有类:
import io.realm.annotations.RealmModule
import io.realm.annotations.RealmNamingPolicy
@RealmModule(
allClasses = true,
classNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES,
fieldNamingPolicy = RealmNamingPolicy.LOWER_CASE_WITH_UNDERSCORES
)
open class MyModule
您还可以在类级别定义命名策略,它会覆盖模块级别的设置:
import io.realm.RealmObject
import io.realm.annotations.RealmClass
import io.realm.annotations.RealmNamingPolicy
@RealmClass(fieldNamingPolicy = RealmNamingPolicy.PASCAL_CASE)
open class Frog : RealmObject {
var name: String? = null
var age = 0
var species: String? = null
var owner: String? = null
constructor(name: String?, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
Rename a Class 重命名类
默认情况下,Realm 数据库使用模型类中定义的名称在内部表示类。在某些情况下,您可能希望更改此行为:
- 在不同的包中支持多个具有相同简单名称的模型类。
- 为了更轻松地跨平台工作,因为命名约定不同。
- 使用比 Realm 数据库强制执行的 57 个字符限制更长的类名。
- 在 Kotlin 中更改类名而不强制迁移。
使用 @RealmClass 注解重命名一个类:
import io.realm.RealmObject
import io.realm.annotations.RealmClass
@RealmClass(name = "Short_Bodied_Tailless_Amphibian")
open class Frog : RealmObject {
var name: String? = null
var age = 0
var species: String? = null
var owner: String? = null
constructor(name: String?, age: Int, species: String?, owner: String?) {
this.name = name
this.age = age
this.species = species
this.owner = owner
}
constructor() {} // RealmObject subclasses must provide an empty constructor
}
从你的 Realm 模式中省略类
默认情况下,您的应用程序的 Realm 模式包括所有继承了 RealmObject 的类。如果您只想包含在您的 Realm 模式中继承了 RealmObject 类的子集,您可以在模块中包含该类的子集并使用该模块打开您的 Realm:
import io.realm.annotations.RealmModule
@RealmModule(classes = [Frog::class, Fly::class])
open class MyModule