Realm 中的@LinkingObjects 注解是如何工作的

How does the @LinkingObjects annotation in Realm work

我有一个 Android 应用程序,它使用 SQLite 及其 json1 扩展作为其数据库后端。虽然这有效,但操作 JSON 所需的 SQL 很难理解,甚至更难维护。因此,我目前正在尝试使用 Realm 作为替代方案。虽然 Realm 在很大程度上是直观的,但 LinkingObjects 是一个我不完全理解的功能。考虑以下我目前使用的 classes

public class GridNode extends RealmObject
{
 @PrimaryKey
 private int id = 0;   
 @Index
 private int lx = 0;
 @Index
 private int ly = 0;

 @LinkingObjects("gridnode")
 private final RealmResults<PassPoint> passpoints = null;

 //getters, setters & constructors
}


public class PassPoint extends RealmObject
{
 private GridNode gridnode;//each passpoint refers to one distinct GridNode object
 private int hits;
 private int lastVisited;

 //getters, setters & constructors
} 

在我的数据的当前 SQLite 版本中,我通过引用其 AUTO_INCREMENTing id 字段来识别每个 PassPoint 使用的 GridNode。使用 Realm,事情变得简单多了,因为我可以简单地将 GridNode 本身用作 PassPoint 的属性。

这是事情变得不太清楚的地方。假设我通过 运行 一个 RealmQuery 例如

Realm 中检索一个现有的 GridNode
myrealm.where(GridNode.class).equalTo("lx",23).equalTo("ly",32).findFirst();

阅读字里行间我得出的结论是 运行 宁此查询不仅会获取我之后的 GridNode,而且 运行 使用我的

的隐式查询
@LinkingObjects("gridnode")
private final RealmResults<PassPoint> passpoints = null;

用于检索引用相关 GridNode 的所有 PassPoint 对象的列表的注释。

非常方便,但我发现自己想知道这是否需要付出代价 - 运行 该查询所需的时间。假设我还有一些其他 classes 也引用 GridNodes,在这种情况下,我将有进一步的 @LinkingObjets 注释,这将导致进一步的隐式查询?

与此相反,如果我只是记录一个 GridNode id,那么我可以在需要时自己处理识别相关的 GridNode 吗?实际上,用便利换取速度和响应能力?

或者我只是简单地读错了字里行间,这根本不是 @LinkingObjects 的工作原理?

另一件不太清楚的事情 - 正如您将注意到的 gridnodePassPoint class 的私有成员。那么我如何才能在我的 GridNode class 中创建 @LinkingObjects("gridnode") 注释,而编译器不会抱怨我试图访问一个从 PassPoint 外部不可见的成员 class?

Reading between the lines I have concluded that running this query will not only fetch the GridNode I am after but run an implicit query

没有。不完全是。

正如 Realm 文档所述here

All fetches (including queries) are lazy in Realm, and the data is never copied.

这意味着定义查询的简单情况就是这样 - 它定义了它。但在用户明确请求之前,它不会 evaluate/execute 查询。因此,具有查询字段(例如 LinkingObjects 字段)的对象提供了一种简单的方法,用户可以通过该方法执行查询,但不会仅仅因为对象本身已加载就自动执行。只有 运行 当 findFirstfindAll(或类似的)调用时。

因此,如果您从未真正访问过 GridNode.passpoints 字段,则它永远不会被执行。

您可以通过一个简单的实验向自己证明这一点:-

  1. 从没有链接 PassPoint 的领域中检索 GridNode
  2. 访问链接对象字段并检查它是否为空。
  3. 向领域添加一个新的 Passpoint 并引用相同的 GridNode
  4. 重新测试您在步骤 1 中检索到的同一对象的链接对象字段,您应该会看到查询结果现在包含新的 Passpoint.

关于你的第二个问题,简单的回答是你的模型字段的保护级别只适用于你数据的Java模型;它不适用于底层 Realm 模型。