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

CRUD - 读取 - Java SDK

在此页面上

  • 读取操作
  • 读取特征
  • 结果不是副本
  • 结果出现延迟
  • 引用被保留
  • 关于本页中的示例
  • 从 Realm 读取
  • 按主键查找特定对象
  • 查询给定类型的所有对象
  • 根据对象属性筛选查询
  • 对查询结果进行排序
  • 查询关系
  • 查询反向关系
  • 聚合数据

您可以读回存储在Realm中的数据。 Realm SDK 的标准数据访问模式是按顺序查找、过滤和排序对象。 随着应用的增长和查询变得更加复杂,为了从Realm获得最佳性能,请围绕对Realm 读取特征的深入理解来设计应用程序的数据访问模式。

当您围绕 Realm 中读取的以下三个关键特征设计应用的数据访问模式时,您可以确信自己正在尽可能高效地读取数据。

查询的结果不是数据副本:修改查询结果将直接修改磁盘上的数据。这种内存映射还意味着结果是实时的:也就是说,它们始终反映磁盘上的当前状态。

Realm会推迟查询的执行,直到您访问权限结果。 您可以链接多个过滤和排序操作,而无需额外的工作来进程中间状态。

Realm 对象模型的一项优势是,Realm 会自动将对象的所有关系保留为直接引用,因此您可以通过查询结果直接遍历关系图。

直接引用或指针允许您直接通过该引用访问相关对象的属性。

当您需要直接使用对象时,其他数据库通常会将对象从数据库存储复制到应用程序内存中。由于应用程序对象包含直接引用,因此您只有一个选项:将每个直接引用所引用的对象从数据库中复制出来(如果需要),或仅复制每个对象的外键并在该对象被访问的情况下使用该键来查询此对象。如果选择将引用的对象复制到应用程序内存中,则可能会为从未访问过的对象占用大量资源;但是,如果选择仅复制外键,引用的对象查找则可能会导致应用程序变慢。

Realm 使用零拷贝活动对象绕过所有这些操作。Realm 对象访问器使用内存映射直接指向数据库存储,因此 Realm 中的对象与应用程序内存中的查询结果没有区别。因此,您可从任一查询结果遍历整个 Realm 的直接引用。

本页上的示例使用具有两种 Realm 对象类型的项目管理应用的Realm 数据模型: ProjectTaskProject具有零个或多个Tasks

请参阅 ProjectTask 这两个类的模式,如下所示:

ProjectTask.java
import org.bson.types.ObjectId;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.RealmClass;
import io.realm.annotations.Required;
public class ProjectTask extends RealmObject {
@PrimaryKey
public ObjectId _id;
@Required
public String name;
public String assignee;
public int progressMinutes;
public boolean isComplete;
public int priority;
@Required
public String _partition;
}
Project.java
import org.bson.types.ObjectId;
import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.RealmClass;
import io.realm.annotations.Required;
public class Project extends RealmObject {
@PrimaryKey
public ObjectId _id;
@Required
public String name;
public RealmList<ProjectTask> tasks = new RealmList<>();
}
ProjectTask.kt
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import io.realm.annotations.Required
import org.bson.types.ObjectId
open class ProjectTask(
@PrimaryKey
var _id: ObjectId = ObjectId(),
@Required
var name: String = "",
var assignee: String? = null,
var progressMinutes: Int = 0,
var isComplete: Boolean = false,
var priority: Int = 0,
var _partition: String = ""
): RealmObject()
Project.kt
import io.realm.RealmList
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import io.realm.annotations.Required
import org.bson.types.ObjectId
open class Project(
@PrimaryKey
var _id: ObjectId = ObjectId(),
@Required
var name: String = "",
var tasks: RealmList<ProjectTask> = RealmList(),
): RealmObject()

Realm 读取一般包括以下步骤:

所有查询、过滤和排序操作都会返回一个结果集合。 结果集合是实时的,这意味着它们始终包含关联查询的最新结果。

重要

UI 线程上的同步读写

默认情况下,只能使用异步事务在应用程序的用户界面线程中读取或写入域。也就是说,除非您明确允许使用同步方法,否则您只能在 Android 应用程序的主线程中使用名称以单词 Async 结尾的 Realm 方法。

此限制是为了应用程序用户的利益:在 UI 线程上执行读写操作,可能导致 UI 交互无响应或速度缓慢,所以通常来说,最好以异步方式或在后台线程中处理这些操作。但是,如果应用程序需要在 UI 线程上使用同步 Realm 读取或写入,则可以通过以下 SyncConfiguration 选项明确支持使用同步方法:

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread."
);
}
});
val config = SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm with reads and writes allowed on the UI thread.")
}
})

要查找具有特定主键的对象,请打开一个域并使用RealmQuery.equalTo()在主键字段中查询所需的主键。 方法:

ProjectTask task = realm.where(ProjectTask.class).equalTo("_id", PRIMARY_KEY_VALUE.get()).findFirst();
Log.v("EXAMPLE", "Fetched object by primary key: " + task);
val task = realm.where(ProjectTask::class.java)
.equalTo("_id", ObjectId.get()).findFirst()
Log.v("EXAMPLE", "Fetched object by primary key: $task")

任何读取的第一步都是获取域中特定类型的所有对象。 使用此结果集合,您可以对类型或过滤的所有实例进行操作并进行排序以优化结果。

要访问权限ProjectTaskProject的所有实例,请使用where()方法指定一个类:

RealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class);
RealmQuery<Project> projectsQuery = realm.where(Project.class);
val tasksQuery = realm.where(ProjectTask::class.java)
val projectsQuery = realm.where(Project::class.java)

筛选器根据一个或多个对象属性的值选择结果子集。 Realm 提供了一个功能齐全的查询引擎,您可以使用它来定义筛选器。 最常见的用例是查找特定属性与特定值匹配的对象。 此外,您还可以比较字符串、聚合数字集合以及使用逻辑运算符来构建复杂的查询。

在以下示例中,我们使用查询引擎的比较运算符执行以下操作:

  • 通过将 priority 属性值与阈值数字进行比较来查找高优先级任务,而高于该阈值的优先级可视为高优先级。

  • 通过查看 progressMinutes 属性是否在特定范围内来查找刚刚启动或短时间运行的任务。

  • 通过查找assignee属性等于 null 的任务来查找未分配的任务。

  • 通过查看 assignee 属性是否在名称列表中来查找分配给团队成员 Ali 或 Jamie 的任务。

RealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class);
Log.i("EXAMPLE", "High priority tasks: " + tasksQuery.greaterThan("priority", 5).count());
Log.i("EXAMPLE", "Just-started or short tasks: " + tasksQuery.between("progressMinutes", 1, 10).count());
Log.i("EXAMPLE", "Unassigned tasks: " + tasksQuery.isNull("assignee").count());
Log.i("EXAMPLE", "Ali or Jamie's tasks: " + tasksQuery.in("assignee", new String[]{"Ali", "Jamie"}).count());
val tasksQuery = realm.where(ProjectTask::class.java)
Log.i(
"EXAMPLE", "High priority tasks: " + tasksQuery.greaterThan(
"priority",
5
).count()
)
Log.i(
"EXAMPLE", "Just-started or short tasks: " + tasksQuery.between(
"progressMinutes",
1,
10
).count()
)
Log.i(
"EXAMPLE",
"Unassigned tasks: " + tasksQuery.isNull("assignee").count()
)
Log.i(
"EXAMPLE", "Ali or Jamie's tasks: " + tasksQuery.`in`(
"assignee", arrayOf(
"Ali",
"Jamie"
)
).count()
)

排序操作允许您配置 Realm 返回查询对象的顺序。您可以根据结果集合中对象的一个或多个属性进行排序。

仅当结果已进行排序时,Realm 才能保证结果顺序一致。

以下代码按名称倒序排列项目(即 “降序”)。

RealmQuery<Project> projectsQuery = realm.where(Project.class);
RealmResults<Project> results = projectsQuery.sort("name", Sort.DESCENDING).findAll();
val projectsQuery = realm.where(Project::class.java)
val results = projectsQuery.sort("name", Sort.DESCENDING).findAll()

考虑类HumanCat之间的以下关系。 这种安排允许每个人拥有一只猫:

import org.bson.types.ObjectId;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class Human extends RealmObject {
@PrimaryKey
private ObjectId _id = new ObjectId();
private String name;
private Cat cat;
public Human(String name) {
this.name = name;
}
public Human() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public ObjectId get_id() {
return _id;
}
}
import org.bson.types.ObjectId;
import io.realm.RealmObject;
import io.realm.RealmResults;
import io.realm.annotations.LinkingObjects;
import io.realm.annotations.PrimaryKey;
public class Cat extends RealmObject {
@PrimaryKey
private ObjectId _id = new ObjectId();
private String name = null;
@LinkingObjects("cat")
private final RealmResults<Human> owner = null;
public Cat(String name) {
this.name = name;
}
public Cat() {
}
public ObjectId get_id() {
return _id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RealmResults<Human> getOwner() {
return owner;
}
}

要查询此关系,请在查询中使用点表示法来访问权限链接对象的任何属性:

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread."
);
realm.executeTransaction(transactionRealm -> {
Human owner = transactionRealm.where(Human.class).equalTo("cat.name", "bucky").findFirst();
Cat cat = owner.getCat();
Log.v("EXAMPLE", "Queried for humans with cats named 'bucky'. Found " + owner.getName() + ", who owns " + cat.getName());
});
realm.close();
}
});

考虑类PersonDog之间的以下关系。 这种安排允许每个人拥有一只狗:

import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import org.bson.types.ObjectId
open class Person(var name : String? = null) : RealmObject() {
@PrimaryKey
var _id : ObjectId = ObjectId()
var dog: Dog? = null
}
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.LinkingObjects
import io.realm.annotations.PrimaryKey
import org.bson.types.ObjectId
open class Dog(var name : String? = null): RealmObject() {
@PrimaryKey
var _id : ObjectId = ObjectId()
@LinkingObjects("dog")
val owner: RealmResults<Person>? = null
}

要查询此关系,请在查询中使用点表示法来访问权限链接对象的任何属性:

val config = SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread."
)
realm.executeTransaction { transactionRealm ->
val owner = transactionRealm.where<Person>().equalTo("dog.name", "henry").findFirst()
val dog = owner?.dog
Log.v("EXAMPLE", "Queried for people with dogs named 'henry'. Found $owner, owner of $dog")
}
realm.close()
}
})

考虑类CatHuman之间的以下关系。 在此示例中,所有猫都链接到其人类(或多个人类,如果多个人类对象引用同一只猫)。 Realm会根据您为@LinkingObjects注解提供的字段名称,为您计算每只猫的所有者:

import org.bson.types.ObjectId;
import io.realm.RealmObject;
import io.realm.RealmResults;
import io.realm.annotations.LinkingObjects;
import io.realm.annotations.PrimaryKey;
public class Cat extends RealmObject {
@PrimaryKey
private ObjectId _id = new ObjectId();
private String name = null;
@LinkingObjects("cat")
private final RealmResults<Human> owner = null;
public Cat(String name) {
this.name = name;
}
public Cat() {
}
public ObjectId get_id() {
return _id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RealmResults<Human> getOwner() {
return owner;
}
}
import org.bson.types.ObjectId;
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class Human extends RealmObject {
@PrimaryKey
private ObjectId _id = new ObjectId();
private String name;
private Cat cat;
public Human(String name) {
this.name = name;
}
public Human() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public ObjectId get_id() {
return _id;
}
}

要查询此关系,请在查询中使用点表示法来访问权限链接对象的任何属性:

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v("EXAMPLE", "Successfully opened a realm.");
realm.executeTransaction(transactionRealm -> {
Cat cat = transactionRealm.where(Cat.class)
.equalTo("owner.name", "steven").findFirst();
Human owner = cat.getOwner().first();
Log.v("EXAMPLE", "Queried for cats with owners named 'steven'. Found " + cat.getName() + ", owned by " + owner.getName());
});
realm.close();
}
});

考虑类DogPerson之间的以下关系。 在此示例中,所有狗都链接到其所有者(或多个所有者,如果多个人员对象引用同一只狗)。 Realm 会根据您为@LinkingObjects注解提供的字段名称,为您计算每只狗的主人:

import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.LinkingObjects
import io.realm.annotations.PrimaryKey
import org.bson.types.ObjectId
open class Dog(var name : String? = null): RealmObject() {
@PrimaryKey
var _id : ObjectId = ObjectId()
@LinkingObjects("dog")
val owner: RealmResults<Person>? = null
}
import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import org.bson.types.ObjectId
open class Person(var name : String? = null) : RealmObject() {
@PrimaryKey
var _id : ObjectId = ObjectId()
var dog: Dog? = null
}

要查询此关系,请在查询中使用点表示法来访问权限链接对象的任何属性:

val config = SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread."
)
realm.executeTransaction { transactionRealm ->
val dog = transactionRealm.where<Dog>()
.equalTo("owner.name", "dwayne").findFirst()
val owner = dog?.owner?.first()
Log.v("EXAMPLE", "Queried for dogs with owners named 'dwayne'. Found $dog, owned by $owner")
}
realm.close()
}
})
RealmQuery<ProjectTask> tasksQuery = realm.where(ProjectTask.class);
/*
Aggregate operators do not support dot-notation, so you
cannot directly operate on a property of all of the objects
in a collection property.
You can operate on a numeric property of the top-level
object, however:
*/
Log.i("EXAMPLE", "Tasks average priority: " + tasksQuery.average("priority"));
val tasksQuery = realm.where(ProjectTask::class.java)
/*
Aggregate operators do not support dot-notation, so you
cannot directly operate on a property of all of the objects
in a collection property.
You can operate on a numeric property of the top-level
object, however:
*/Log.i("EXAMPLE", "Tasks average priority: " + tasksQuery.average("priority"))

后退

创建