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

定义 Realm 对象模型 - Java SDK

在此页面上

  • 定义 Realm 对象
  • 扩展 RealmObject
  • 实施 RealmModel
  • 列表
  • 定义嵌入式对象字段
  • 注解
  • 主键
  • 必填字段
  • 可选字段
  • 默认字段值
  • 为字段创建索引
  • 忽略字段
  • 重命名字段
  • 重命名类
  • 从 Realm 模式中省略类

要在应用程序中定义 Realm 对象,请创建 RealmObject的子类或实现RealmModel。

重要

  • 所有 Realm 对象都必须提供一个空的构造函数。

  • 所有 Realm 对象都必须使用 Java 中的 public 可见性修饰符或 Kotlin 中的 open 可见性修饰符。

注意

类名不得超过 57 个 UTF-8 字符。

以下代码块显示了一个描述 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

以下代码块显示了一个描述 Frog 的 Realm 对象。此 Frog 类可以存储在 Realm 中,因为它 implements RealmModel 类并使用 @RealmClass 注释:

import io.realm.RealmModel;
import io.realm.annotations.RealmClass;
@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
@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;
@RealmClass(embedded=true)
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
@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;
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 或是 int

  • Long 或是 long

  • Short 或是 short

  • Byte 或是 byte[]

非原始类型可以包含值null作为主键值,但仅限于特定类型的一个对象,因为每个主键值必须是唯一的。 尝试将具有现有主键的对象插入到 Realm 将导致RealmPrimaryKeyConstraintException。

Realm 自动对主键字段创建索引,因此您可以根据主键有效地读取和修改对象。

将某一类型的任何对象添加到 Realm 后,您无法更改该对象类型的主键字段。如果您使用 Sync,则在后端模式中定义主键后,您将无法更改对象的主键字段。

嵌入式对象不能包含主键。

您可以选择使用 @PrimaryKey 注解将对象类型的主键定义为 对象模式 的一部分:

import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class Frog extends RealmObject {
@PrimaryKey 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 {
@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
}
import io.realm.RealmObject;
import io.realm.annotations.Required;
public class Frog extends RealmObject {
@Required 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 {
@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
}

标有 Java 对象类型和 Kotlin 可空类型(以?结尾)的字段默认可为空。默认情况下,所有其他类型(基元、不可为 null 的 Kotlin 对象类型)都是必需的。您可以使用@Required注解标记可为 null 的字段,以防止该字段持有 null 值。 RealmList永远不能为 null,但您可以使用@Required注解来防止列表中的对象持有 null 值,即使基本类型允许这样做。您无法将RealmObject子类型的RealmList标记为必填项。

可以根据需要使用以下类型:

  • String

  • UUID

  • ObjectId

  • Integer

  • Long

  • Short

  • Byte 或是 byte[]

  • Boolean

  • Float

  • Double

  • Date

  • RealmList

intRealmList 类型等基元类型是隐式必需的。RealmObject 类型的字段始终可以为 null,并且不能设为必填字段。

重要

Kotlin 类型和可空性

在 Kotlin 中,除非您显式向类型添加?后缀,否则默认情况下类型不可为空。您只能注解可为 null 的类型。在非空类型上使用@Required注解会导致编译失败。

默认情况下,可空字段在 Realm 中是可选的,除非使用@Required注解另行指定。 以下类型可为 null:

  • String

  • Date

  • UUID

  • ObjectId

  • Integer

  • Long

  • Short

  • Byte 或是 byte[]

  • Boolean

  • Float

  • Double

默认情况下, intlong等基元类型不可为空,也不能设为可空,因为它们不能设置为空值。

在 Kotlin 中,字段只有在使用 Kotlin ? 操作符将字段标记为可空时才被视为可空,但以下类型除外:

  • String

  • Date

  • UUID

  • ObjectId

  • Decimal128

  • RealmAny

您可以要求任意以 Kotlin ? 运算符结尾的类型,例如 Int?

RealmList 类型默认不可为空,并且不能设为可为空。

要为字段指定默认值,请使用内置语言功能来分配默认值。

使用类构造函数分配默认值:

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
}

注意

默认值和可空性

虽然默认值可确保新创建的对象不能包含值null (除非您指定默认值null ),但它们不会影响字段的可空性。 要将字段设为不可为空,请参阅必填字段。

Realm 中的索引支持高效执行查询。如果没有索引,Realm 就必须执行集合扫描(即扫描集合中的每个文档),以选择与查询相匹配的文档。如果查询存在适当的索引,Realm 就可以使用该索引来限制必须检查的文档数量。

索引是特殊的数据结构,它以易于遍历的形式存储一小部分 realm 数据。索引存储按字段值排序的特定字段的值。索引条目的排序支持高效的相等匹配和基于范围的查询操作。

添加索引可以加快某些查询的速度,但代价是写入速度稍慢,并增加存储和内存开销。索引需要 Realm 文件的空间,因此为属性添加索引会增加 Realm 文件消耗的磁盘空间。每个索引条目至少有 12 个字节。

您可以为以下类型的字段建立索引:

  • String

  • UUID

  • ObjectId

  • Integer 或是 int

  • Long 或是 long

  • Short 或是 short

  • Byte 或是 byte[]

  • Boolean 或是 bool

  • 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;
@Index 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
@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
}

如果您不想将模型中的某个字段保存到 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?
@Ignore 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?
@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
}

注意

SDK 会忽略静态字段和瞬态字段

标记为 statictransient 的字段将始终被忽略,并且不需要 @Ignore 注释。

默认情况下,Realm 在内部使用模型类中定义的名称来表示字段。在某些情况下,您可能想要更改此行为:

  • 要便于在具有不同命名约定的多个平台上工作。

  • 在不强制迁移的情况下更改 Kotlin 中的字段名称。

选择与模型类中使用的名称不同的内部名称,会产生以下影响:

  • 在创建类和字段时,迁移必须使用内部名称。

  • 模式错误报告将使用内部名称。

使用 @RealmField 注解,以重命名字段:

import io.realm.RealmObject;
import io.realm.annotations.RealmField;
public class Frog extends RealmObject {
private String name;
private int age;
@RealmField("latinName") 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
@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
)
public class MyModule {
}
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)
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
@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
}

默认情况下,Realm 在内部使用模型类中定义的名称来表示类。在某些情况下,您可能想要更改此行为:

  • 支持不同软件包中具有相同简单名称的多个模型类。

  • 要便于在具有不同命名约定的多个平台上工作。

  • 要使用长度大于 Realm 执行的 57 个字符限制的类名。

  • 在 Kotlin 中更改类名而不强制迁移。

使用 @RealmClass 注释重命名一个类:

import io.realm.RealmObject;
import io.realm.annotations.RealmClass;
@RealmClass(name = "ShortBodiedTaillessAmphibian")
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
@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 模式包括所有扩展 RealmObject 的类。如果您只想在 Realm 模式中包含扩展 RealmObject 的类的子集,则可以在模块中包含该类的子集,并使用该模块打开 Realm:

import io.realm.annotations.RealmModule;
@RealmModule(classes = { Frog.class, Fly.class })
public class MyModule {
}
import io.realm.annotations.RealmModule
@RealmModule(classes = [Frog::class, Fly::class])
open class MyModule

后退

模型数据

来年

关系