定义 Realm 对象模型 - Java SDK
在此页面上
定义 Realm 对象
要在应用程序中定义Realm 对象,请创建 RealmObject的子类或实现RealmModel。
重要
所有 Realm 对象都必须提供一个空的构造函数。
所有 Realm 对象都必须使用 Java 中的
public
可见性修饰符或 Kotlin 中的open
可见性修饰符。
注意
类名不得超过 57 个 UTF-8 字符。
扩展 RealmObject
以下代码块显示了一个描述 Frog 的 Realm 对象。此 Frog 类可以存储在 Realm 中,因为它 extends
RealmObject
类。
import io.realm.RealmObject; // To add an object to your Realm Schema, extend RealmObject public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
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
实施 RealmModel
以下代码块显示了一个描述 Frog 的 Realm 对象。此 Frog 类可以存储在 Realm 中,因为它 implements
RealmModel
类并使用 @RealmClass
注释:
import io.realm.RealmModel; import io.realm.annotations.RealmClass; public class Frog implements RealmModel { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog() {} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
重要
所有 Realm 对象都必须使用 public
可见性修饰符。
import io.realm.RealmModel import io.realm.annotations.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
类方法。Realm 对象由实现 RealmModel
创建,可通过 RealmObject
类静态访问这些相同的方法:
// With RealmObject frogRealmObject.isValid(); frogRealmObject.addChangeListener(listener); // With RealmModel RealmObject.isValid(frogRealmModel); RealmObject.addChangeListener(frogRealmModel, listener);
// With RealmObject frogRealmObject?.isValid frogRealmObject?.addChangeListener(listener) // With RealmModel RealmObject.isValid(frogRealmModel) RealmObject.addChangeListener(frogRealmModel, listener)
列表
Realm 对象可以包含非 Realm 对象数据类型的列表:
与Realm对象列表不同,这些列表可以包含 null 值。 如果不允许空值,请使用@Required注解。
import io.realm.RealmList; import io.realm.RealmObject; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; private RealmList<String> favoriteColors; public Frog(String name, int age, String species, String owner, RealmList<String> favoriteColors) { this.name = name; this.age = age; this.species = species; this.owner = owner; this.favoriteColors = favoriteColors; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public RealmList<String> getFavoriteColors() { return favoriteColors; } public void setFavoriteColors(RealmList<String> favoriteColors) { this.favoriteColors = favoriteColors; } }
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 提供了在其他对象中嵌套对象的功能。这有几个优点:
如果使用同步,则对象会转换为遵循非规范化数据模型的 MongoDB 文档。
当您删除包含另一个对象的对象时,删除操作会将两个对象都从 Realm 中删除,这样未使用的对象不会在 Realm 文件中累积,也不会占用用户移动设备上的宝贵空间。
要嵌入对象,请将您想要嵌套在另一个类中的类的@RealmClass注解的embedded
属性设立为true
:
import io.realm.RealmObject; import io.realm.annotations.RealmClass; public class Fly extends RealmObject { private String name; public Fly(String name) { this.name = name; } public Fly() {} // RealmObject subclasses must provide an empty constructor }
import io.realm.RealmObject import io.realm.annotations.RealmClass 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; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; private Fly lastMeal; public Frog(String name, int age, String species, String owner, Fly lastMeal) { this.name = name; this.age = age; this.species = species; this.owner = owner; this.lastMeal = lastMeal; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public Fly getLastMeal() { return lastMeal; } public void setLastMeal(Fly lastMeal) { this.lastMeal = lastMeal; } }
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 }
注解
使用注解自定义 Realm 对象模型。
主键
版本 10.6.0 的新增功能:Realm 会自动索引主键字段。此前,Realm 仅自动索引 String
主键。
Realm 将标有 @PrimaryKey 注解的字段视为其相应对象模式的主键。主键受到以下限制:
您只能为每个对象模式定义一个主键。
主键值在 Realm 中对象的所有实例中必须是唯一的。 尝试插入重复的主键值会导致RealmPrimaryKeyConstraintException。
主键值不可变。要更改某一对象的主键值,必须删除原始对象并插入具有其他主键值的新对象。
嵌入式对象无法定义主键。
您可以使用以下任何类型创建主键:
String
UUID
ObjectId
Integer
orint
Long
orlong
Short
orshort
Byte
orbyte[]
非原始类型可以包含值null
作为主键值,但仅限于特定类型的一个对象,因为每个主键值必须是唯一的。 尝试将具有现有主键的对象插入到 Realm 将导致RealmPrimaryKeyConstraintException。
Realm 自动对主键字段创建索引,因此您可以根据主键有效地读取和修改对象。
将某一类型的任何对象添加到域后,您无法更改该对象类型的主键字段。 如果您使用 Sync,则在后端模式中定义主键后,您将无法更改对象的主键字段。
嵌入式对象不能包含主键。
您可以选择使用 @PrimaryKey 注解将对象类型的主键定义为 对象模式 的一部分:
import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.PrimaryKey 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 }
必填字段
import io.realm.RealmObject; import io.realm.annotations.Required; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.Required 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 }
可选字段
标有Java对象类型和Kotlin可空类型(以?
结尾)的字段默认可为 null。 默认,所有其他类型(基元、不可为 null 的Kotlin对象类型)都是必需的。 您可以使用@Required注解标记可为 null 的字段,以防止该字段持有 null 值。 RealmList永远不能为 null,但您可以使用@Required
注解来防止列表中的对象持有 null 值,即使基本类型允许这样做。 您无法将RealmObject
子类型的RealmList
标记为必填项。
可以根据需要使用以下类型:
String
UUID
ObjectId
Integer
Long
Short
Byte
orbyte[]
Boolean
Float
Double
Date
RealmList
int
和 RealmList
类型等基元类型是隐式必需的。RealmObject
类型的字段始终可以为 null,并且不能设为必填字段。
默认情况下,可空字段在 Realm 中是可选的,除非使用@Required注解另行指定。 以下类型可为 null:
String
Date
UUID
ObjectId
Integer
Long
Short
Byte
orbyte[]
Boolean
Float
Double
默认, int
和long
等基元类型不可为空,也不能设为可空,因为它们不能设立为空值。
默认字段值
要为字段指定默认值,请使用内置语言功能来分配默认值。
使用类构造函数分配默认值:
import io.realm.RealmObject; public class Frog extends RealmObject { private String name = "Kitty"; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
在字段声明中指定默认值:
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 }
为字段创建索引
Realm 中的索引支持高效执行查询。如果没有索引,Realm 就必须执行集合扫描(即扫描集合中的每个文档),以选择与查询相匹配的文档。如果查询存在适当的索引,Realm 就可以使用该索引来限制必须检查的文档数量。
索引是特殊的数据结构,它以易于遍历的形式存储一小部分 realm 数据。索引存储按字段值排序的特定字段的值。索引条目的排序支持高效的相等匹配和基于范围的查询操作。
添加索引可以加快某些查询的速度,但代价是写入速度稍慢,并增加存储和内存开销。索引需要 Realm 文件的空间,因此为属性添加索引会增加 Realm 文件消耗的磁盘空间。每个索引条目至少有 12 个字节。
您可以为以下类型的字段建立索引:
String
UUID
ObjectId
Integer
orint
Long
orlong
Short
orshort
Byte
orbyte[]
Boolean
orbool
Date
RealmAny
Realm 为带有 @Index 注解的字段创建索引。
要为字段建立索引,请使用 @Index 注解:
import io.realm.RealmObject; import io.realm.annotations.Index; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.Index 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,则可以忽略该字段。
使用 @Ignore 注解,忽略 Realm 对象模型中的字段:
import io.realm.RealmObject; import io.realm.annotations.Ignore; public class Frog extends RealmObject { private String name; private int age; private String species; // can you ever really own a frog persistently? private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
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? 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 }
注意
SDK 会忽略静态字段和瞬态字段
标记为 static
或 transient
的字段将始终被忽略,并且不需要 @Ignore
注释。
重命名字段
默认情况下,Realm 在内部使用模型类中定义的名称来表示字段。在某些情况下,您可能想要更改此行为:
要便于在具有不同命名约定的多个平台上工作。
在不强制迁移的情况下更改 Kotlin 中的字段名称。
选择与模型类中使用的名称不同的内部名称,会产生以下影响:
在创建类和字段时,迁移必须使用内部名称。
模式错误报告将使用内部名称。
使用 @RealmField 注解,以重命名字段:
import io.realm.RealmObject; import io.realm.annotations.RealmField; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.RealmField 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 解释字段名称的方式。
您可以在 模块级别 定义 命名策略 ,这将影响模块中包含的所有类:
import io.realm.annotations.RealmModule; import io.realm.annotations.RealmNamingPolicy; public class MyModule { }
import io.realm.annotations.RealmModule import io.realm.annotations.RealmNamingPolicy open class MyModule
您还可以在类级别定义命名策略,该策略会覆盖模块级别的设置:
import io.realm.RealmObject; import io.realm.annotations.RealmClass; import io.realm.annotations.RealmNamingPolicy; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.RealmClass import io.realm.annotations.RealmNamingPolicy 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 执行的 57 个字符限制的类名。
在 Kotlin 中更改类名而不强制迁移。
使用 @RealmClass 注释重命名一个类:
import io.realm.RealmObject; import io.realm.annotations.RealmClass; public class Frog extends RealmObject { private String name; private int age; private String species; private String owner; public Frog(String name, int age, String species, String owner) { this.name = name; this.age = age; this.species = species; this.owner = owner; } public Frog(){} // RealmObject subclasses must provide an empty constructor public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSpecies() { return species; } public void setSpecies(String species) { this.species = species; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } }
import io.realm.RealmObject import io.realm.annotations.RealmClass 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; public class MyModule { }
import io.realm.annotations.RealmModule open class MyModule